diff --git a/.clang-format b/.clang-format new file mode 100644 index 000000000..9837ca9d4 --- /dev/null +++ b/.clang-format @@ -0,0 +1,37 @@ +--- +Language: Cpp +BasedOnStyle: Chromium +IndentWidth: 4 +ColumnLimit: 100 +UseTab: Never +IndentCaseLabels: true +# do not allow ifs or loops without braces +InsertBraces: true +PointerAlignment: Right + +BreakBeforeBraces: Stroustrup +BreakBeforeBinaryOperators: true + +BinPackArguments: false +BinPackParameters: false + +AlignConsecutiveMacros: + Enabled: true + AcrossComments: true + AcrossEmptyLines: false + +AlignConsecutiveDeclarations: + Enabled: true + AcrossComments: false + AcrossEmptyLines: false + +AlignConsecutiveAssignments: + Enabled: true + AcrossComments: false + AcrossEmptyLines: false + +AlignArrayOfStructures: Left +SortIncludes: Never +SpaceAfterCStyleCast: True +AllowShortEnumsOnASingleLine: false +... diff --git a/.git-blame-ignore-revs b/.git-blame-ignore-revs new file mode 100644 index 000000000..cde81fa99 --- /dev/null +++ b/.git-blame-ignore-revs @@ -0,0 +1,5 @@ +# Run this command to always ignore formatting commits in `git blame` +# git config blame.ignoreRevsFile .git-blame-ignore-revs + +# Formatting commit +985bb5283ffac5991a21911b9ea8bc31ecd758d0 diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index 4d0ea41e0..c9758012c 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -22,3 +22,9 @@ repos: rev: v2.2.5 hooks: - id: codespell + + - repo: https://github.com/pre-commit/mirrors-clang-format + rev: v16.0.6 + hooks: + - id: clang-format + types_or: [c] diff --git a/include/appflags.h b/include/appflags.h index ad6ddf928..a010bdd3c 100644 --- a/include/appflags.h +++ b/include/appflags.h @@ -1,75 +1,79 @@ #pragma once /** - * Base flag added to loaded application, to allow them to call all syscalls by default (the one requiring no extra permission) + * Base flag added to loaded application, to allow them to call all syscalls by default (the one + * requiring no extra permission) */ -#define APPLICATION_FLAG_MAIN 0x1 +#define APPLICATION_FLAG_MAIN 0x1 /** * Flag which combined with ::APPLICATION_FLAG_ISSUER. * The application is given full nvram access after the global seed has been destroyed. */ -#define APPLICATION_FLAG_BOLOS_UPGRADE 0x2 +#define APPLICATION_FLAG_BOLOS_UPGRADE 0x2 -// this flag is set when a valid signature of the loaded application is presented at the end of the bolos application load. -#define APPLICATION_FLAG_SIGNED 0x4 +// this flag is set when a valid signature of the loaded application is presented at the end of the +// bolos application load. +#define APPLICATION_FLAG_SIGNED 0x4 // must be set on one application in the registry which is used -#define APPLICATION_FLAG_BOLOS_UX 0x8 +#define APPLICATION_FLAG_BOLOS_UX 0x8 +// application is allowed to use the raw master seed, if not set, at least a level of derivation is +// required. +#define APPLICATION_FLAG_DERIVE_MASTER 0x10 -// application is allowed to use the raw master seed, if not set, at least a level of derivation is required. -#define APPLICATION_FLAG_DERIVE_MASTER 0x10 +#define APPLICATION_FLAG_SHARED_NVRAM 0x20 +#define APPLICATION_FLAG_GLOBAL_PIN 0x40 -#define APPLICATION_FLAG_SHARED_NVRAM 0x20 -#define APPLICATION_FLAG_GLOBAL_PIN 0x40 - -// This flag means the application is meant to be debugged and allows for dump or core ARM register in -// case of a fault detection -#define APPLICATION_FLAG_DEBUG 0x80 +// This flag means the application is meant to be debugged and allows for dump or core ARM register +// in case of a fault detection +#define APPLICATION_FLAG_DEBUG 0x80 /** - * Mark this application as defaultly booting along with the bootloader (no application menu displayed) - * Only one application can have this at a time. It is managed by the bootloader interface. + * Mark this application as defaultly booting along with the bootloader (no application menu + * displayed) Only one application can have this at a time. It is managed by the bootloader + * interface. */ -#define APPLICATION_FLAG_AUTOBOOT 0x100 +#define APPLICATION_FLAG_AUTOBOOT 0x100 /** * Application is allowed to change the settings */ -#define APPLICATION_FLAG_BOLOS_SETTINGS 0x200 +#define APPLICATION_FLAG_BOLOS_SETTINGS 0x200 -#define APPLICATION_FLAG_CUSTOM_CA 0x400 +#define APPLICATION_FLAG_CUSTOM_CA 0x400 /** * The application main can be called in two ways: * - with first arg (stored in r0) set to 0: The application is called from the dashboard - * - with first arg (stored in r0) set to != 0 (ram address likely): The application is used as a library from another app. + * - with first arg (stored in r0) set to != 0 (ram address likely): The application is used as a + * library from another app. */ -#define APPLICATION_FLAG_LIBRARY 0x800 +#define APPLICATION_FLAG_LIBRARY 0x800 /** * The application won't be shown on the dashboard (somewhat reasonable for pure library) */ -#define APPLICATION_FLAG_NO_RUN 0x1000 +#define APPLICATION_FLAG_NO_RUN 0x1000 #if defined(HAVE_LANGUAGE_PACK) /** * This application is in fact a Language pack! */ -#define APPLICATION_FLAG_LANGUAGE_PACK 0x2000 -#endif //defined(HAVE_LANGUAGE_PACK) +#define APPLICATION_FLAG_LANGUAGE_PACK 0x2000 +#endif // defined(HAVE_LANGUAGE_PACK) /** * Application has been loaded using a secure channel opened using the bootloader's issuer * public key. This application is ledger legit. */ -#define APPLICATION_FLAG_ISSUER 0x4000 +#define APPLICATION_FLAG_ISSUER 0x4000 /** * Application is enabled (when not being updated or removed) */ -#define APPLICATION_FLAG_ENABLED 0x8000 +#define APPLICATION_FLAG_ENABLED 0x8000 /** * Application is actually a Stax background image @@ -80,10 +84,10 @@ * Custom AEM flag to test AEM capabilities without standard UX permissions */ #if defined(BOLOS_DEBUG_UX_PERMISSION_FLAG) - #define APPLICATION_FLAG_AEM_PIN APPLICATION_FLAG_GLOBAL_PIN +#define APPLICATION_FLAG_AEM_PIN APPLICATION_FLAG_GLOBAL_PIN #else - #define APPLICATION_FLAG_AEM_PIN APPLICATION_FLAG_BOLOS_UX -#endif // BOLOS_DEBUG_UX_PERMISSION_FLAG +#define APPLICATION_FLAG_AEM_PIN APPLICATION_FLAG_BOLOS_UX +#endif // BOLOS_DEBUG_UX_PERMISSION_FLAG #ifdef HAVE_BACKGROUND_IMG #define APPLICATION_FLAGS_MASK (0x00000000FFFFFFFFULL) @@ -93,12 +97,12 @@ #define APPLICATION_FLAGS_MASK (0x0000FFFF) #define APPLICATION_FLAG_NEG_MASK (0xFFFF0000) #define APPLICATION_FLAGS_SHIFT (16) -#endif //HAVE_BACKGROUND_IMG +#endif // HAVE_BACKGROUND_IMG -#define GET_COMPLEMENTED_APPLICATION_FLAGS(flags) \ - (((~((flags)&APPLICATION_FLAGS_MASK) << APPLICATION_FLAGS_SHIFT)) | \ - ((flags)&APPLICATION_FLAGS_MASK)) +#define GET_COMPLEMENTED_APPLICATION_FLAGS(flags) \ + (((~((flags) &APPLICATION_FLAGS_MASK) << APPLICATION_FLAGS_SHIFT)) \ + | ((flags) &APPLICATION_FLAGS_MASK)) -#define IS_APPLICATION_FLAGS_SECURE(complemented_flags) \ - (((~(complemented_flags) << APPLICATION_FLAGS_SHIFT) & APPLICATION_FLAG_NEG_MASK) == \ - ((complemented_flags) & APPLICATION_FLAG_NEG_MASK)) +#define IS_APPLICATION_FLAGS_SECURE(complemented_flags) \ + (((~(complemented_flags) << APPLICATION_FLAGS_SHIFT) & APPLICATION_FLAG_NEG_MASK) \ + == ((complemented_flags) &APPLICATION_FLAG_NEG_MASK)) diff --git a/include/arch.h b/include/arch.h index 8b6b38341..aa56a174f 100644 --- a/include/arch.h +++ b/include/arch.h @@ -10,23 +10,23 @@ #include "os_hal.h" #if defined(ST31) - #include +#include #endif #if defined(ST33J2M0) - #include +#include #endif #if defined(ST33K1M5) - #include +#include #endif #if defined(X86) - #define NATIVE_PRINT - #include - #include +#define NATIVE_PRINT +#include +#include #endif -#endif // HAVE_BOLOS +#endif // HAVE_BOLOS #define WIDE diff --git a/include/checks.h b/include/checks.h index 43efc7641..f0e9851af 100644 --- a/include/checks.h +++ b/include/checks.h @@ -1,31 +1,31 @@ /******************************************************************************* -* Ledger Nano S - Secure firmware -* (c) 2022 Ledger -* -* Licensed under the Apache License, Version 2.0 (the "License"); -* you may not use this file except in compliance with the License. -* You may obtain a copy of the License at -* -* http://www.apache.org/licenses/LICENSE-2.0 -* -* Unless required by applicable law or agreed to in writing, software -* distributed under the License is distributed on an "AS IS" BASIS, -* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -* See the License for the specific language governing permissions and -* limitations under the License. -********************************************************************************/ + * Ledger Nano S - Secure firmware + * (c) 2022 Ledger + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT 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(CHECKS_H) #define CHECKS_H #if !defined(HAVE_BOLOS) && defined(HAVE_PENDING_REVIEW_SCREEN) -#define CHECK_NOT_AUDITED_TLV_TAG 0x9F -#define CHECK_NOT_AUDITED_TLV_VAL 0x01 -#define CHECK_NOT_AUDITED_MAX_LEN 0x40 +#define CHECK_NOT_AUDITED_TLV_TAG 0x9F +#define CHECK_NOT_AUDITED_TLV_VAL 0x01 +#define CHECK_NOT_AUDITED_MAX_LEN 0x40 void check_audited_app(void); -#endif // !defined(HAVE_BOLOS) && defined(HAVE_PENDING_REVIEW_SCREEN) +#endif // !defined(HAVE_BOLOS) && defined(HAVE_PENDING_REVIEW_SCREEN) #endif diff --git a/include/cx.h b/include/cx.h index be4507740..e74f62f4b 100644 --- a/include/cx.h +++ b/include/cx.h @@ -1,20 +1,20 @@ /******************************************************************************* -* Ledger Nano S - Secure firmware -* (c) 2022 Ledger -* -* Licensed under the Apache License, Version 2.0 (the "License"); -* you may not use this file except in compliance with the License. -* You may obtain a copy of the License at -* -* http://www.apache.org/licenses/LICENSE-2.0 -* -* Unless required by applicable law or agreed to in writing, software -* distributed under the License is distributed on an "AS IS" BASIS, -* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -* See the License for the specific language governing permissions and -* limitations under the License. -********************************************************************************/ + * Ledger Nano S - Secure firmware + * (c) 2022 Ledger + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + ********************************************************************************/ #pragma once diff --git a/include/cx_errors.h b/include/cx_errors.h index 6b5ed37fc..a2b260612 100644 --- a/include/cx_errors.h +++ b/include/cx_errors.h @@ -11,93 +11,95 @@ * Checks the error code of a function. * @hideinitializer */ -#define CX_CHECK(call) do { \ - error = call; \ - if (error) { \ - goto end; \ - } \ - } while (0) +#define CX_CHECK(call) \ + do { \ + error = call; \ + if (error) { \ + goto end; \ + } \ + } while (0) /** * Checks the error code of a function and ignore * it if CX_CARRY. * @hideinitializer */ -#define CX_CHECK_IGNORE_CARRY(call) do { \ - error = call; \ - if (error && error != CX_CARRY) { \ - goto end; \ - } \ - } while (0) +#define CX_CHECK_IGNORE_CARRY(call) \ + do { \ + error = call; \ + if (error && error != CX_CARRY) { \ + goto end; \ + } \ + } while (0) /** Success. */ -#define CX_OK 0x00000000 +#define CX_OK 0x00000000 /** There exists a carry at the end of the operation. */ -#define CX_CARRY 0xFFFFFF21 +#define CX_CARRY 0xFFFFFF21 /** * Multi Precision Integer processor is locked: * operations can be done. */ -#define CX_LOCKED 0xFFFFFF81 +#define CX_LOCKED 0xFFFFFF81 /** * Multi Precision Integer processor is unlocked: * operations can't be done. */ -#define CX_UNLOCKED 0xFFFFFF82 +#define CX_UNLOCKED 0xFFFFFF82 /** * Multi Precision Integer processor is not locked: * it cannot be unlocked. */ -#define CX_NOT_LOCKED 0xFFFFFF83 +#define CX_NOT_LOCKED 0xFFFFFF83 /** * Multi Precision Integer processor is already locked: * it cannot be locked. */ -#define CX_NOT_UNLOCKED 0xFFFFFF84 +#define CX_NOT_UNLOCKED 0xFFFFFF84 /** Internal error */ -#define CX_INTERNAL_ERROR 0xFFFFFF85 +#define CX_INTERNAL_ERROR 0xFFFFFF85 /** * A parameter has an invalid size. */ -#define CX_INVALID_PARAMETER_SIZE 0xFFFFFF86 +#define CX_INVALID_PARAMETER_SIZE 0xFFFFFF86 /** * A parameter has an invalid value. */ -#define CX_INVALID_PARAMETER_VALUE 0xFFFFFF87 +#define CX_INVALID_PARAMETER_VALUE 0xFFFFFF87 /** A parameter is invalid. */ -#define CX_INVALID_PARAMETER 0xFFFFFF88 +#define CX_INVALID_PARAMETER 0xFFFFFF88 /** * A value is not invertible. */ -#define CX_NOT_INVERTIBLE 0xFFFFFF89 +#define CX_NOT_INVERTIBLE 0xFFFFFF89 /** A value overflow occurred. */ -#define CX_OVERFLOW 0xFFFFFF8A +#define CX_OVERFLOW 0xFFFFFF8A /** Memory is full: allocation is not possible anymore. */ -#define CX_MEMORY_FULL 0xFFFFFF8B +#define CX_MEMORY_FULL 0xFFFFFF8B /** A quadratic residue cannot be computed. */ -#define CX_NO_RESIDUE 0xFFFFFF8C +#define CX_NO_RESIDUE 0xFFFFFF8C /** Point at infinity is hit. */ -#define CX_EC_INFINITE_POINT 0xFFFFFF41 +#define CX_EC_INFINITE_POINT 0xFFFFFF41 /** Point is invalid: it does not belong to the curve. */ -#define CX_EC_INVALID_POINT 0xFFFFFFA2 +#define CX_EC_INVALID_POINT 0xFFFFFFA2 /** Curve is invalid. */ -#define CX_EC_INVALID_CURVE 0xFFFFFFA3 +#define CX_EC_INVALID_CURVE 0xFFFFFFA3 /** Type of error code */ typedef uint32_t cx_err_t; diff --git a/include/cx_stubs.h b/include/cx_stubs.h index 0baddc8d5..4cc5de86f 100644 --- a/include/cx_stubs.h +++ b/include/cx_stubs.h @@ -1,134 +1,134 @@ #pragma once // auto-generated by cxsdk.py -#define _NR_cx_aes_dec_block 0x00 -#define _NR_cx_aes_enc_block 0x01 -#define _NR_cx_aes_gcm_check_tag 0x02 -#define _NR_cx_aes_gcm_decrypt_and_auth 0x03 -#define _NR_cx_aes_gcm_encrypt_and_tag 0x04 -#define _NR_cx_aes_gcm_finish 0x05 -#define _NR_cx_aes_gcm_init 0x06 -#define _NR_cx_aes_gcm_set_key 0x07 -#define _NR_cx_aes_gcm_start 0x08 -#define _NR_cx_aes_gcm_update_aad 0x09 -#define _NR_cx_aes_gcm_update 0x0a -#define _NR_cx_aes_init_key_no_throw 0x0b -#define _NR_cx_aes_iv_no_throw 0x0c -#define _NR_cx_aes_no_throw 0x0d -#define _NR_cx_aes_siv_encrypt 0x0e -#define _NR_cx_aes_siv_decrypt 0x0f -#define _NR_cx_aes_siv_init 0x10 -#define _NR_cx_aes_siv_set_key 0x11 -#define _NR_cx_aes_siv_start 0x12 -#define _NR_cx_aes_siv_update_aad 0x13 -#define _NR_cx_aes_siv_finish 0x14 -#define _NR_cx_aes_siv_update 0x15 -#define _NR_cx_blake2b 0x16 -#define _NR_cx_blake2b_final 0x17 -#define _NR_cx_blake2b_get_output_size 0x18 -#define _NR_cx_blake2b_init2_no_throw 0x19 -#define _NR_cx_blake2b_init_no_throw 0x1a -#define _NR_cx_blake2b_update 0x1b -#define _NR_cx_cipher_enc_dec 0x1c -#define _NR_cx_cipher_finish 0x1d -#define _NR_cx_cipher_init 0x1e -#define _NR_cx_cipher_setiv 0x1f -#define _NR_cx_cipher_setkey 0x20 -#define _NR_cx_cipher_setup 0x21 -#define _NR_cx_cipher_set_padding 0x22 -#define _NR_cx_cipher_update 0x23 -#define _NR_cx_cmac 0x24 -#define _NR_cx_constant_time_eq 0x25 -#define _NR_cx_crc16 0x26 -#define _NR_cx_crc16_update 0x27 -#define _NR_cx_crc32 0x28 -#define _NR_cx_decode_coord 0x29 -#define _NR_cx_ecdh_no_throw 0x2f -#define _NR_cx_ecdsa_sign_no_throw 0x30 -#define _NR_cx_ecdsa_verify_no_throw 0x31 -#define _NR_cx_ecfp_add_point_no_throw 0x32 -#define _NR_cx_ecfp_decode_sig_der 0x33 -#define _NR_cx_ecfp_encode_sig_der 0x34 -#define _NR_cx_ecfp_generate_pair2_no_throw 0x35 -#define _NR_cx_ecfp_generate_pair_no_throw 0x36 -#define _NR_cx_ecfp_init_private_key_no_throw 0x37 -#define _NR_cx_ecfp_init_public_key_no_throw 0x38 -#define _NR_cx_ecfp_scalar_mult_no_throw 0x39 -#define _NR_cx_ecschnorr_sign_no_throw 0x3a -#define _NR_cx_ecschnorr_verify 0x3b -#define _NR_cx_eddsa_get_public_key_internal 0x3c -#define _NR_cx_eddsa_get_public_key_no_throw 0x3d -#define _NR_cx_eddsa_sign_no_throw 0x3e -#define _NR_cx_eddsa_verify_no_throw 0x3f -#define _NR_cx_edwards_compress_point_no_throw 0x40 -#define _NR_cx_edwards_decompress_point_no_throw 0x41 -#define _NR_cx_encode_coord 0x42 -#define _NR_cx_hash_final 0x43 -#define _NR_cx_hash_get_info 0x44 -#define _NR_cx_hash_get_size 0x45 -#define _NR_cx_hash_init 0x46 -#define _NR_cx_hash_init_ex 0x47 -#define _NR_cx_hash_no_throw 0x48 -#define _NR_cx_hash_ripemd160 0x49 -#define _NR_cx_hash_sha256 0x4a -#define _NR_cx_hash_sha512 0x4b -#define _NR_cx_hash_update 0x4c -#define _NR_cx_hkdf_expand 0x4d -#define _NR_cx_hkdf_extract 0x4e -#define _NR_cx_hmac_final 0x4f -#define _NR_cx_hmac_init 0x50 -#define _NR_cx_hmac_no_throw 0x51 -#define _NR_cx_hmac_ripemd160_init_no_throw 0x52 -#define _NR_cx_hmac_sha224_init 0x53 -#define _NR_cx_hmac_sha256 0x54 -#define _NR_cx_hmac_sha256_init_no_throw 0x55 -#define _NR_cx_hmac_sha384_init 0x56 -#define _NR_cx_hmac_sha512 0x57 -#define _NR_cx_hmac_sha512_init_no_throw 0x58 -#define _NR_cx_hmac_update 0x59 -#define _NR_cx_keccak_init_no_throw 0x5a -#define _NR_cx_math_addm_no_throw 0x5b -#define _NR_cx_math_add_no_throw 0x5c -#define _NR_cx_math_cmp_no_throw 0x5d -#define _NR_cx_math_invintm_no_throw 0x5e -#define _NR_cx_math_invprimem_no_throw 0x5f -#define _NR_cx_math_is_prime_no_throw 0x60 -#define _NR_cx_math_modm_no_throw 0x61 -#define _NR_cx_math_multm_no_throw 0x62 -#define _NR_cx_math_mult_no_throw 0x63 -#define _NR_cx_math_next_prime_no_throw 0x64 -#define _NR_cx_math_powm_no_throw 0x65 -#define _NR_cx_math_subm_no_throw 0x66 -#define _NR_cx_math_sub_no_throw 0x67 -#define _NR_cx_memxor 0x68 -#define _NR_cx_pbkdf2_hmac 0x69 -#define _NR_cx_pbkdf2_no_throw 0x6a -#define _NR_cx_ripemd160_final 0x6b -#define _NR_cx_ripemd160_init_no_throw 0x6c -#define _NR_cx_ripemd160_update 0x6d -#define _NR_cx_rng_no_throw 0x6e -#define _NR_cx_rng_rfc6979 0x6f -#define _NR_cx_rng_rfc6979_init 0x70 -#define _NR_cx_rng_rfc6979_next 0x71 -#define _NR_cx_rng_u32_range_func 0x72 -#define _NR_cx_sha224_init_no_throw 0x73 -#define _NR_cx_sha256_final 0x74 -#define _NR_cx_sha256_init_no_throw 0x75 -#define _NR_cx_sha256_update 0x76 -#define _NR_cx_sha384_init_no_throw 0x77 -#define _NR_cx_sha3_final 0x78 -#define _NR_cx_sha3_get_output_size 0x79 -#define _NR_cx_sha3_init_no_throw 0x7a -#define _NR_cx_sha3_update 0x7b -#define _NR_cx_sha3_xof_init_no_throw 0x7c -#define _NR_cx_sha512_final 0x7d -#define _NR_cx_sha512_init_no_throw 0x7e -#define _NR_cx_sha512_update 0x7f -#define _NR_cx_shake128_init_no_throw 0x80 -#define _NR_cx_shake256_init_no_throw 0x81 -#define _NR_cx_swap_buffer32 0x82 -#define _NR_cx_swap_buffer64 0x83 -#define _NR_cx_swap_uint32 0x84 -#define _NR_cx_swap_uint64 0x85 -#define _NR_cx_x25519 0x86 -#define _NR_cx_x448 0x87 +#define _NR_cx_aes_dec_block 0x00 +#define _NR_cx_aes_enc_block 0x01 +#define _NR_cx_aes_gcm_check_tag 0x02 +#define _NR_cx_aes_gcm_decrypt_and_auth 0x03 +#define _NR_cx_aes_gcm_encrypt_and_tag 0x04 +#define _NR_cx_aes_gcm_finish 0x05 +#define _NR_cx_aes_gcm_init 0x06 +#define _NR_cx_aes_gcm_set_key 0x07 +#define _NR_cx_aes_gcm_start 0x08 +#define _NR_cx_aes_gcm_update_aad 0x09 +#define _NR_cx_aes_gcm_update 0x0a +#define _NR_cx_aes_init_key_no_throw 0x0b +#define _NR_cx_aes_iv_no_throw 0x0c +#define _NR_cx_aes_no_throw 0x0d +#define _NR_cx_aes_siv_encrypt 0x0e +#define _NR_cx_aes_siv_decrypt 0x0f +#define _NR_cx_aes_siv_init 0x10 +#define _NR_cx_aes_siv_set_key 0x11 +#define _NR_cx_aes_siv_start 0x12 +#define _NR_cx_aes_siv_update_aad 0x13 +#define _NR_cx_aes_siv_finish 0x14 +#define _NR_cx_aes_siv_update 0x15 +#define _NR_cx_blake2b 0x16 +#define _NR_cx_blake2b_final 0x17 +#define _NR_cx_blake2b_get_output_size 0x18 +#define _NR_cx_blake2b_init2_no_throw 0x19 +#define _NR_cx_blake2b_init_no_throw 0x1a +#define _NR_cx_blake2b_update 0x1b +#define _NR_cx_cipher_enc_dec 0x1c +#define _NR_cx_cipher_finish 0x1d +#define _NR_cx_cipher_init 0x1e +#define _NR_cx_cipher_setiv 0x1f +#define _NR_cx_cipher_setkey 0x20 +#define _NR_cx_cipher_setup 0x21 +#define _NR_cx_cipher_set_padding 0x22 +#define _NR_cx_cipher_update 0x23 +#define _NR_cx_cmac 0x24 +#define _NR_cx_constant_time_eq 0x25 +#define _NR_cx_crc16 0x26 +#define _NR_cx_crc16_update 0x27 +#define _NR_cx_crc32 0x28 +#define _NR_cx_decode_coord 0x29 +#define _NR_cx_ecdh_no_throw 0x2f +#define _NR_cx_ecdsa_sign_no_throw 0x30 +#define _NR_cx_ecdsa_verify_no_throw 0x31 +#define _NR_cx_ecfp_add_point_no_throw 0x32 +#define _NR_cx_ecfp_decode_sig_der 0x33 +#define _NR_cx_ecfp_encode_sig_der 0x34 +#define _NR_cx_ecfp_generate_pair2_no_throw 0x35 +#define _NR_cx_ecfp_generate_pair_no_throw 0x36 +#define _NR_cx_ecfp_init_private_key_no_throw 0x37 +#define _NR_cx_ecfp_init_public_key_no_throw 0x38 +#define _NR_cx_ecfp_scalar_mult_no_throw 0x39 +#define _NR_cx_ecschnorr_sign_no_throw 0x3a +#define _NR_cx_ecschnorr_verify 0x3b +#define _NR_cx_eddsa_get_public_key_internal 0x3c +#define _NR_cx_eddsa_get_public_key_no_throw 0x3d +#define _NR_cx_eddsa_sign_no_throw 0x3e +#define _NR_cx_eddsa_verify_no_throw 0x3f +#define _NR_cx_edwards_compress_point_no_throw 0x40 +#define _NR_cx_edwards_decompress_point_no_throw 0x41 +#define _NR_cx_encode_coord 0x42 +#define _NR_cx_hash_final 0x43 +#define _NR_cx_hash_get_info 0x44 +#define _NR_cx_hash_get_size 0x45 +#define _NR_cx_hash_init 0x46 +#define _NR_cx_hash_init_ex 0x47 +#define _NR_cx_hash_no_throw 0x48 +#define _NR_cx_hash_ripemd160 0x49 +#define _NR_cx_hash_sha256 0x4a +#define _NR_cx_hash_sha512 0x4b +#define _NR_cx_hash_update 0x4c +#define _NR_cx_hkdf_expand 0x4d +#define _NR_cx_hkdf_extract 0x4e +#define _NR_cx_hmac_final 0x4f +#define _NR_cx_hmac_init 0x50 +#define _NR_cx_hmac_no_throw 0x51 +#define _NR_cx_hmac_ripemd160_init_no_throw 0x52 +#define _NR_cx_hmac_sha224_init 0x53 +#define _NR_cx_hmac_sha256 0x54 +#define _NR_cx_hmac_sha256_init_no_throw 0x55 +#define _NR_cx_hmac_sha384_init 0x56 +#define _NR_cx_hmac_sha512 0x57 +#define _NR_cx_hmac_sha512_init_no_throw 0x58 +#define _NR_cx_hmac_update 0x59 +#define _NR_cx_keccak_init_no_throw 0x5a +#define _NR_cx_math_addm_no_throw 0x5b +#define _NR_cx_math_add_no_throw 0x5c +#define _NR_cx_math_cmp_no_throw 0x5d +#define _NR_cx_math_invintm_no_throw 0x5e +#define _NR_cx_math_invprimem_no_throw 0x5f +#define _NR_cx_math_is_prime_no_throw 0x60 +#define _NR_cx_math_modm_no_throw 0x61 +#define _NR_cx_math_multm_no_throw 0x62 +#define _NR_cx_math_mult_no_throw 0x63 +#define _NR_cx_math_next_prime_no_throw 0x64 +#define _NR_cx_math_powm_no_throw 0x65 +#define _NR_cx_math_subm_no_throw 0x66 +#define _NR_cx_math_sub_no_throw 0x67 +#define _NR_cx_memxor 0x68 +#define _NR_cx_pbkdf2_hmac 0x69 +#define _NR_cx_pbkdf2_no_throw 0x6a +#define _NR_cx_ripemd160_final 0x6b +#define _NR_cx_ripemd160_init_no_throw 0x6c +#define _NR_cx_ripemd160_update 0x6d +#define _NR_cx_rng_no_throw 0x6e +#define _NR_cx_rng_rfc6979 0x6f +#define _NR_cx_rng_rfc6979_init 0x70 +#define _NR_cx_rng_rfc6979_next 0x71 +#define _NR_cx_rng_u32_range_func 0x72 +#define _NR_cx_sha224_init_no_throw 0x73 +#define _NR_cx_sha256_final 0x74 +#define _NR_cx_sha256_init_no_throw 0x75 +#define _NR_cx_sha256_update 0x76 +#define _NR_cx_sha384_init_no_throw 0x77 +#define _NR_cx_sha3_final 0x78 +#define _NR_cx_sha3_get_output_size 0x79 +#define _NR_cx_sha3_init_no_throw 0x7a +#define _NR_cx_sha3_update 0x7b +#define _NR_cx_sha3_xof_init_no_throw 0x7c +#define _NR_cx_sha512_final 0x7d +#define _NR_cx_sha512_init_no_throw 0x7e +#define _NR_cx_sha512_update 0x7f +#define _NR_cx_shake128_init_no_throw 0x80 +#define _NR_cx_shake256_init_no_throw 0x81 +#define _NR_cx_swap_buffer32 0x82 +#define _NR_cx_swap_buffer64 0x83 +#define _NR_cx_swap_uint32 0x84 +#define _NR_cx_swap_uint64 0x85 +#define _NR_cx_x25519 0x86 +#define _NR_cx_x448 0x87 diff --git a/include/decorators.h b/include/decorators.h index 8be37270d..639fb7741 100644 --- a/include/decorators.h +++ b/include/decorators.h @@ -1,68 +1,68 @@ #pragma once #ifndef SYSCALL - // #define SYSCALL syscall - #define SYSCALL +// #define SYSCALL syscall +#define SYSCALL #endif #ifndef TASKSWITCH - // #define TASKSWITCH taskswitch - #define TASKSWITCH +// #define TASKSWITCH taskswitch +#define TASKSWITCH #endif #ifndef SUDOCALL - // #define SUDOCALL sudocall - #define SUDOCALL +// #define SUDOCALL sudocall +#define SUDOCALL #endif #ifndef LIBCALL - // #define LIBCALL libcall - #define LIBCALL +// #define LIBCALL libcall +#define LIBCALL #endif #ifndef SHARED - // #define SHARED shared - #define SHARED +// #define SHARED shared +#define SHARED #endif #ifndef PERMISSION - #define PERMISSION(...) +#define PERMISSION(...) #endif #ifndef PLENGTH - #define PLENGTH(...) +#define PLENGTH(...) #endif #ifndef CXPORT - #define CXPORT(...) +#define CXPORT(...) #endif #ifndef TASKLEVEL - #define TASKLEVEL(...) +#define TASKLEVEL(...) #endif #ifndef OPT_NONE - #if defined(__clang__) - #define OPT_NONE __attribute__((optnone)) - #elif defined(__GNUC__) - #define OPT_NONE __attribute__((optimize("O0"))) - #else - #define OPT_NONE - #endif +#if defined(__clang__) +#define OPT_NONE __attribute__((optnone)) +#elif defined(__GNUC__) +#define OPT_NONE __attribute__((optimize("O0"))) +#else +#define OPT_NONE +#endif #endif #ifndef FALL_THROUGH - #if defined(__GNUC__) && __GNUC__ >= 7 || defined(__clang__) && __clang_major__ >= 12 - #define FALL_THROUGH __attribute__ ((fallthrough)) - #else - #define FALL_THROUGH ((void)0) - #endif +#if defined(__GNUC__) && __GNUC__ >= 7 || defined(__clang__) && __clang_major__ >= 12 +#define FALL_THROUGH __attribute__((fallthrough)) +#else +#define FALL_THROUGH ((void) 0) +#endif #endif #ifndef WARN_UNUSED_RESULT - #define WARN_UNUSED_RESULT __attribute__ ((warn_unused_result)) +#define WARN_UNUSED_RESULT __attribute__((warn_unused_result)) #endif #ifndef DEPRECATED - #define DEPRECATED __attribute__ ((deprecated)) +#define DEPRECATED __attribute__((deprecated)) #endif diff --git a/include/errors.h b/include/errors.h index a258d1293..54b52ca47 100644 --- a/include/errors.h +++ b/include/errors.h @@ -1,20 +1,20 @@ /******************************************************************************* -* Ledger Nano S - Secure firmware -* (c) 2022 Ledger -* -* Licensed under the Apache License, Version 2.0 (the "License"); -* you may not use this file except in compliance with the License. -* You may obtain a copy of the License at -* -* http://www.apache.org/licenses/LICENSE-2.0 -* -* Unless required by applicable law or agreed to in writing, software -* distributed under the License is distributed on an "AS IS" BASIS, -* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -* See the License for the specific language governing permissions and -* limitations under the License. -********************************************************************************/ + * Ledger Nano S - Secure firmware + * (c) 2022 Ledger + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT 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(ERRORS_H) #define ERRORS_H @@ -23,47 +23,47 @@ * Applications-reserved error codes ranges. * The Operating System do not use any error code within these ranges. */ -#define ERR_APP_RANGE_01 0xB000 -#define ERR_APP_RANGE_02 0xC000 -#define ERR_APP_RANGE_03 0xD000 -#define ERR_APP_RANGE_04 0xE000 +#define ERR_APP_RANGE_01 0xB000 +#define ERR_APP_RANGE_02 0xC000 +#define ERR_APP_RANGE_03 0xD000 +#define ERR_APP_RANGE_04 0xE000 /** * I/O error codes range. * */ -#define ERR_IOL_RANGE 0x1000 +#define ERR_IOL_RANGE 0x1000 // Generic subcategories. -#define ERR_GEN_SUB_01 0x0100 -#define ERR_GEN_SUB_02 0x0200 -#define ERR_GEN_SUB_03 0x0300 -#define ERR_GEN_SUB_04 0x0400 -#define ERR_GEN_SUB_05 0x0500 -#define ERR_GEN_SUB_06 0x0600 -#define ERR_GEN_SUB_07 0x0700 -#define ERR_GEN_SUB_08 0x0800 -#define ERR_GEN_SUB_09 0x0900 -#define ERR_GEN_SUB_0D 0x0D00 -#define ERR_GEN_SUB_0E 0x0E00 +#define ERR_GEN_SUB_01 0x0100 +#define ERR_GEN_SUB_02 0x0200 +#define ERR_GEN_SUB_03 0x0300 +#define ERR_GEN_SUB_04 0x0400 +#define ERR_GEN_SUB_05 0x0500 +#define ERR_GEN_SUB_06 0x0600 +#define ERR_GEN_SUB_07 0x0700 +#define ERR_GEN_SUB_08 0x0800 +#define ERR_GEN_SUB_09 0x0900 +#define ERR_GEN_SUB_0D 0x0D00 +#define ERR_GEN_SUB_0E 0x0E00 // Generic identifiers. enum sdk_generic_identifiers { - ERR_GEN_ID_01 = 0x01, - ERR_GEN_ID_02, - ERR_GEN_ID_03, - ERR_GEN_ID_04, - ERR_GEN_ID_05, - ERR_GEN_ID_06, - ERR_GEN_ID_07, - ERR_GEN_ID_08, - ERR_GEN_ID_09, - ERR_GEN_ID_0A, - ERR_GEN_ID_0B, - ERR_GEN_ID_0C, - ERR_GEN_ID_0D, - ERR_GEN_ID_0E, - ERR_GEN_ID_0F + ERR_GEN_ID_01 = 0x01, + ERR_GEN_ID_02, + ERR_GEN_ID_03, + ERR_GEN_ID_04, + ERR_GEN_ID_05, + ERR_GEN_ID_06, + ERR_GEN_ID_07, + ERR_GEN_ID_08, + ERR_GEN_ID_09, + ERR_GEN_ID_0A, + ERR_GEN_ID_0B, + ERR_GEN_ID_0C, + ERR_GEN_ID_0D, + ERR_GEN_ID_0E, + ERR_GEN_ID_0F }; /** @@ -74,82 +74,81 @@ enum sdk_generic_identifiers { * Reset issues (RST), * BLE issues (BLE). */ -#define ERR_IOL_OFW (ERR_IOL_RANGE + ERR_GEN_SUB_01) -#define ERR_IOL_HDR (ERR_IOL_RANGE + ERR_GEN_SUB_02) -#define ERR_IOL_STA (ERR_IOL_RANGE + ERR_GEN_SUB_03) -#define ERR_IOL_RST (ERR_IOL_RANGE + ERR_GEN_SUB_04) +#define ERR_IOL_OFW (ERR_IOL_RANGE + ERR_GEN_SUB_01) +#define ERR_IOL_HDR (ERR_IOL_RANGE + ERR_GEN_SUB_02) +#define ERR_IOL_STA (ERR_IOL_RANGE + ERR_GEN_SUB_03) +#define ERR_IOL_RST (ERR_IOL_RANGE + ERR_GEN_SUB_04) #if defined(HAVE_BLE) -# define ERR_IOL_BLE (ERR_IOL_RANGE + ERR_GEN_SUB_05) -#endif // HAVE_BLE - -#define SWO_IOL_OFW_01 (ERR_IOL_OFW + ERR_GEN_ID_01) // 0x1101 -#define SWO_IOL_OFW_02 (ERR_IOL_OFW + ERR_GEN_ID_02) // 0x1102 -#define SWO_IOL_OFW_03 (ERR_IOL_OFW + ERR_GEN_ID_03) // 0x1103 -#define SWO_IOL_OFW_04 (ERR_IOL_OFW + ERR_GEN_ID_04) // 0x1104 -#define SWO_IOL_OFW_05 (ERR_IOL_OFW + ERR_GEN_ID_05) // 0x1105 - -#define SWO_IOL_HDR_01 (ERR_IOL_HDR + ERR_GEN_ID_01) // 0x1201 -#define SWO_IOL_HDR_02 (ERR_IOL_HDR + ERR_GEN_ID_02) // 0x1202 -#define SWO_IOL_HDR_03 (ERR_IOL_HDR + ERR_GEN_ID_03) // 0x1203 -#define SWO_IOL_HDR_04 (ERR_IOL_HDR + ERR_GEN_ID_04) // 0x1204 -#define SWO_IOL_HDR_05 (ERR_IOL_HDR + ERR_GEN_ID_05) // 0x1205 -#define SWO_IOL_HDR_06 (ERR_IOL_HDR + ERR_GEN_ID_06) // 0x1206 -#define SWO_IOL_HDR_07 (ERR_IOL_HDR + ERR_GEN_ID_07) // 0x1207 -#define SWO_IOL_HDR_08 (ERR_IOL_HDR + ERR_GEN_ID_08) // 0x1208 - -#define SWO_IOL_STA_01 (ERR_IOL_STA + ERR_GEN_ID_01) // 0x1301 -#define SWO_IOL_STA_02 (ERR_IOL_STA + ERR_GEN_ID_02) // 0x1302 -#define SWO_IOL_STA_03 (ERR_IOL_STA + ERR_GEN_ID_03) // 0x1303 -#define SWO_IOL_STA_04 (ERR_IOL_STA + ERR_GEN_ID_04) // 0x1304 - -#define SWO_IOL_RST_01 (ERR_IOL_RST + ERR_GEN_ID_01) // 0x1401 -#define SWO_IOL_RST_02 (ERR_IOL_RST + ERR_GEN_ID_02) // 0x1402 -#define SWO_IOL_RST_03 (ERR_IOL_RST + ERR_GEN_ID_03) // 0x1403 -#define SWO_IOL_RST_05 (ERR_IOL_RST + ERR_GEN_ID_05) // 0x1405 - Do not move this value. +#define ERR_IOL_BLE (ERR_IOL_RANGE + ERR_GEN_SUB_05) +#endif // HAVE_BLE + +#define SWO_IOL_OFW_01 (ERR_IOL_OFW + ERR_GEN_ID_01) // 0x1101 +#define SWO_IOL_OFW_02 (ERR_IOL_OFW + ERR_GEN_ID_02) // 0x1102 +#define SWO_IOL_OFW_03 (ERR_IOL_OFW + ERR_GEN_ID_03) // 0x1103 +#define SWO_IOL_OFW_04 (ERR_IOL_OFW + ERR_GEN_ID_04) // 0x1104 +#define SWO_IOL_OFW_05 (ERR_IOL_OFW + ERR_GEN_ID_05) // 0x1105 + +#define SWO_IOL_HDR_01 (ERR_IOL_HDR + ERR_GEN_ID_01) // 0x1201 +#define SWO_IOL_HDR_02 (ERR_IOL_HDR + ERR_GEN_ID_02) // 0x1202 +#define SWO_IOL_HDR_03 (ERR_IOL_HDR + ERR_GEN_ID_03) // 0x1203 +#define SWO_IOL_HDR_04 (ERR_IOL_HDR + ERR_GEN_ID_04) // 0x1204 +#define SWO_IOL_HDR_05 (ERR_IOL_HDR + ERR_GEN_ID_05) // 0x1205 +#define SWO_IOL_HDR_06 (ERR_IOL_HDR + ERR_GEN_ID_06) // 0x1206 +#define SWO_IOL_HDR_07 (ERR_IOL_HDR + ERR_GEN_ID_07) // 0x1207 +#define SWO_IOL_HDR_08 (ERR_IOL_HDR + ERR_GEN_ID_08) // 0x1208 + +#define SWO_IOL_STA_01 (ERR_IOL_STA + ERR_GEN_ID_01) // 0x1301 +#define SWO_IOL_STA_02 (ERR_IOL_STA + ERR_GEN_ID_02) // 0x1302 +#define SWO_IOL_STA_03 (ERR_IOL_STA + ERR_GEN_ID_03) // 0x1303 +#define SWO_IOL_STA_04 (ERR_IOL_STA + ERR_GEN_ID_04) // 0x1304 + +#define SWO_IOL_RST_01 (ERR_IOL_RST + ERR_GEN_ID_01) // 0x1401 +#define SWO_IOL_RST_02 (ERR_IOL_RST + ERR_GEN_ID_02) // 0x1402 +#define SWO_IOL_RST_03 (ERR_IOL_RST + ERR_GEN_ID_03) // 0x1403 +#define SWO_IOL_RST_05 (ERR_IOL_RST + ERR_GEN_ID_05) // 0x1405 - Do not move this value. #if defined(HAVE_BLE) -# define SWO_IOL_BLE_01 (ERR_IOL_BLE + ERR_GEN_ID_01) // 0x1501 -# define SWO_IOL_BLE_02 (ERR_IOL_BLE + ERR_GEN_ID_02) // 0x1502 -# define SWO_IOL_BLE_03 (ERR_IOL_BLE + ERR_GEN_ID_03) // 0x1503 -# define SWO_IOL_BLE_04 (ERR_IOL_BLE + ERR_GEN_ID_04) // 0x1504 -# define SWO_IOL_BLE_05 (ERR_IOL_BLE + ERR_GEN_ID_05) // 0x1505 -# define SWO_IOL_BLE_06 (ERR_IOL_BLE + ERR_GEN_ID_06) // 0x1506 -# define SWO_IOL_BLE_07 (ERR_IOL_BLE + ERR_GEN_ID_07) // 0x1507 -# define SWO_IOL_BLE_08 (ERR_IOL_BLE + ERR_GEN_ID_08) // 0x1508 -# define SWO_IOL_BLE_09 (ERR_IOL_BLE + ERR_GEN_ID_09) // 0x1509 -# define SWO_IOL_BLE_0A (ERR_IOL_BLE + ERR_GEN_ID_0A) // 0x150A -# define SWO_IOL_BLE_0B (ERR_IOL_BLE + ERR_GEN_ID_0B) // 0x150B -# define SWO_IOL_BLE_0C (ERR_IOL_BLE + ERR_GEN_ID_0C) // 0x150C -#endif // HAVE_BLE - -#define SWO_SEC_PIN_15 0x5515 +#define SWO_IOL_BLE_01 (ERR_IOL_BLE + ERR_GEN_ID_01) // 0x1501 +#define SWO_IOL_BLE_02 (ERR_IOL_BLE + ERR_GEN_ID_02) // 0x1502 +#define SWO_IOL_BLE_03 (ERR_IOL_BLE + ERR_GEN_ID_03) // 0x1503 +#define SWO_IOL_BLE_04 (ERR_IOL_BLE + ERR_GEN_ID_04) // 0x1504 +#define SWO_IOL_BLE_05 (ERR_IOL_BLE + ERR_GEN_ID_05) // 0x1505 +#define SWO_IOL_BLE_06 (ERR_IOL_BLE + ERR_GEN_ID_06) // 0x1506 +#define SWO_IOL_BLE_07 (ERR_IOL_BLE + ERR_GEN_ID_07) // 0x1507 +#define SWO_IOL_BLE_08 (ERR_IOL_BLE + ERR_GEN_ID_08) // 0x1508 +#define SWO_IOL_BLE_09 (ERR_IOL_BLE + ERR_GEN_ID_09) // 0x1509 +#define SWO_IOL_BLE_0A (ERR_IOL_BLE + ERR_GEN_ID_0A) // 0x150A +#define SWO_IOL_BLE_0B (ERR_IOL_BLE + ERR_GEN_ID_0B) // 0x150B +#define SWO_IOL_BLE_0C (ERR_IOL_BLE + ERR_GEN_ID_0C) // 0x150C +#endif // HAVE_BLE + +#define SWO_SEC_PIN_15 0x5515 /** * The process is successful. */ -#define SWO_SUCCESS 0x9000 +#define SWO_SUCCESS 0x9000 // Legacy -#define EXCEPTION 0x1 // keep original value // SWO_MUI_UNK_01 -#define INVALID_PARAMETER 0x2 // keep original value // SWO_CRY_LEN_01 -#define EXCEPTION_SECURITY 0x3 // keep original value // SWO_MUI_UNK_02 -#define INVALID_STATE 0x4 // keep original value // SWO_CRY_VAL_01 -#define EXCEPTION_IO_RESET 0x5 // keep original value // SWO_IOL_RST_01 -#define NOT_ENOUGH_SPACE 0x6 // keep original value // SWO_CRY_VAL_01 -#define EXCEPTION_OVERFLOW 0x7 // keep original value // SWO_MUI_UNK_03 -#define INVALID_CRC 0x8 // keep original value // SWO_MUI_UNK_0C -#define INVALID_CHECKSUM 0x9 // keep original value // SWO_MUI_UNK_0D -#define INVALID_COUNTER 0xA // keep original value // SWO_MUI_UNK_0E -#define NOT_SUPPORTED 0xB // keep original value // SWO_MUI_UNK_0F -#define TIMEOUT 0xC // keep original value // SWO_MUI_UNK_10 -#define EXCEPTION_PIC 0xD // keep original value // SWO_MUI_UNK_11 -#define EXCEPTION_APPEXIT 0xE // keep original value // SWO_MUI_UNK_12 -#define EXCEPTION_IO_OVERFLOW 0xF // keep original value // SWO_MUI_UNK_13 -#define EXCEPTION_IO_HEADER 0x10 // keep original value // SWO_MUI_UNK_14 -#define EXCEPTION_IO_STATE 0x11 // keep original value // SWO_MUI_UNK_15 -#define EXCEPTION_CXPORT 0x12 // keep original value // SWO_MUI_UNK_16 -#define EXCEPTION_SYSTEM 0x13 // keep original value // SWO_MUI_UNK_17 - - -#endif // ERRORS_H +#define EXCEPTION 0x1 // keep original value // SWO_MUI_UNK_01 +#define INVALID_PARAMETER 0x2 // keep original value // SWO_CRY_LEN_01 +#define EXCEPTION_SECURITY 0x3 // keep original value // SWO_MUI_UNK_02 +#define INVALID_STATE 0x4 // keep original value // SWO_CRY_VAL_01 +#define EXCEPTION_IO_RESET 0x5 // keep original value // SWO_IOL_RST_01 +#define NOT_ENOUGH_SPACE 0x6 // keep original value // SWO_CRY_VAL_01 +#define EXCEPTION_OVERFLOW 0x7 // keep original value // SWO_MUI_UNK_03 +#define INVALID_CRC 0x8 // keep original value // SWO_MUI_UNK_0C +#define INVALID_CHECKSUM 0x9 // keep original value // SWO_MUI_UNK_0D +#define INVALID_COUNTER 0xA // keep original value // SWO_MUI_UNK_0E +#define NOT_SUPPORTED 0xB // keep original value // SWO_MUI_UNK_0F +#define TIMEOUT 0xC // keep original value // SWO_MUI_UNK_10 +#define EXCEPTION_PIC 0xD // keep original value // SWO_MUI_UNK_11 +#define EXCEPTION_APPEXIT 0xE // keep original value // SWO_MUI_UNK_12 +#define EXCEPTION_IO_OVERFLOW 0xF // keep original value // SWO_MUI_UNK_13 +#define EXCEPTION_IO_HEADER 0x10 // keep original value // SWO_MUI_UNK_14 +#define EXCEPTION_IO_STATE 0x11 // keep original value // SWO_MUI_UNK_15 +#define EXCEPTION_CXPORT 0x12 // keep original value // SWO_MUI_UNK_16 +#define EXCEPTION_SYSTEM 0x13 // keep original value // SWO_MUI_UNK_17 + +#endif // ERRORS_H diff --git a/include/exceptions.h b/include/exceptions.h index e7b75517f..c7992cf1b 100644 --- a/include/exceptions.h +++ b/include/exceptions.h @@ -11,102 +11,115 @@ typedef unsigned short exception_t; typedef struct try_context_s try_context_t; #if (defined(ST31) || defined(ST33) || defined(ST33K1M5)) && defined(__arm__) - //#include - // GCC/LLVM declare way too big jmp context, reduce them to what is used on CM0+ +// #include +// GCC/LLVM declare way too big jmp context, reduce them to what is used on CM0+ - // jmp context to backup (in increasing order address: r4, r5, r6, r7, r8, r9, r10, r11, SP, setjmpcallPC) - typedef unsigned int jmp_buf[10]; +// jmp context to backup (in increasing order address: r4, r5, r6, r7, r8, r9, r10, r11, SP, +// setjmpcallPC) +typedef unsigned int jmp_buf[10]; - // borrowed from setjmp.h +// borrowed from setjmp.h - #ifdef __GNUC__ - void longjmp(jmp_buf __jmpb, int __retval) __attribute__ ((__noreturn__)); - #else - void longjmp(jmp_buf __jmpb, int __retval); - #endif - int setjmp(jmp_buf __jmpb); +#ifdef __GNUC__ +void longjmp(jmp_buf __jmpb, int __retval) __attribute__((__noreturn__)); +#else +void longjmp(jmp_buf __jmpb, int __retval); +#endif +int setjmp(jmp_buf __jmpb); #else #include #endif struct try_context_s { - jmp_buf jmp_buf; + jmp_buf jmp_buf; - // link to the previous jmp_buf context - try_context_t* previous; + // link to the previous jmp_buf context + try_context_t *previous; - // current exception - exception_t ex; + // current exception + exception_t ex; }; // workaround to make sure defines are replaced by their value for example -#define CPP_CONCAT(x, y) CPP_CONCAT_x(x,y) -#define CPP_CONCAT_x(x, y) x ## y +#define CPP_CONCAT(x, y) CPP_CONCAT_x(x, y) +#define CPP_CONCAT_x(x, y) x##y -SUDOCALL try_context_t* try_context_get(void); +SUDOCALL try_context_t *try_context_get(void); // set the new try context and retrieve the previous one -// SECURITY NOTE: no PLENGTH(sizeof(try_context_t)) set because the value is never dereferenced within the SUDOCALL. +// SECURITY NOTE: no PLENGTH(sizeof(try_context_t)) set because the value is never dereferenced +// within the SUDOCALL. // and is checked before being used in all SYSCALL that would use it. -SUDOCALL try_context_t* try_context_set(try_context_t *context); +SUDOCALL try_context_t *try_context_set(try_context_t *context); // ----------------------------------------------------------------------- // - BEGIN TRY // ----------------------------------------------------------------------- -#define BEGIN_TRY_L(L) \ - { \ - try_context_t __try ## L; - +#define BEGIN_TRY_L(L) \ + { \ + try_context_t __try##L; // ----------------------------------------------------------------------- // - TRY // ----------------------------------------------------------------------- -#define TRY_L(L) \ - /* previous exception context chain is saved within the setjmp r9 save */ \ - __try ## L.ex = setjmp(__try ## L.jmp_buf); \ - if (__try ## L.ex == 0) { \ - __try ## L.previous = try_context_set(&__try ## L); +#define TRY_L(L) \ + /* previous exception context chain is saved within the setjmp r9 save */ \ + __try \ + ##L.ex = setjmp(__try##L.jmp_buf); \ + if (__try##L.ex == 0) { \ + __try \ + ##L.previous = try_context_set(&__try##L); // ----------------------------------------------------------------------- // - EXCEPTION CATCH // ----------------------------------------------------------------------- -#define CATCH_L(L,x) \ - goto CPP_CONCAT(__FINALLY,L); \ - } else if (__try ## L.ex == x) { \ - __try ## L.ex = 0; \ - CLOSE_TRY_L(L); +#define CATCH_L(L, x) \ + goto CPP_CONCAT(__FINALLY, L); \ + } \ + else if (__try##L.ex == x) \ + { \ + __try \ + ##L.ex = 0; \ + CLOSE_TRY_L(L); // ----------------------------------------------------------------------- // - EXCEPTION CATCH OTHER // ----------------------------------------------------------------------- -#define CATCH_OTHER_L(L,e) \ - goto CPP_CONCAT(__FINALLY,L); \ - } else { \ - exception_t e; \ - e = __try ## L.ex; \ - __try ## L.ex = 0; \ - CLOSE_TRY_L(L); +#define CATCH_OTHER_L(L, e) \ + goto CPP_CONCAT(__FINALLY, L); \ + } \ + else \ + { \ + exception_t e; \ + e = __try##L.ex; \ + __try \ + ##L.ex = 0; \ + CLOSE_TRY_L(L); // ----------------------------------------------------------------------- // - EXCEPTION CATCH ALL // ----------------------------------------------------------------------- -#define CATCH_ALL_L(L) \ - goto CPP_CONCAT(__FINALLY,L); \ - } else { \ - __try ## L.ex = 0; \ - CLOSE_TRY_L(L); +#define CATCH_ALL_L(L) \ + goto CPP_CONCAT(__FINALLY, L); \ + } \ + else \ + { \ + __try \ + ##L.ex = 0; \ + CLOSE_TRY_L(L); // ----------------------------------------------------------------------- // - FINALLY // ----------------------------------------------------------------------- -#define FINALLY_L(L) \ - goto CPP_CONCAT(__FINALLY,L); \ - } \ - CPP_CONCAT(__FINALLY,L) : \ - /* has TRY clause ended without nested throw ? */ \ - if (try_context_get() == &__try ## L) { \ - /* restore previous context manually (as a throw would have when caught) */ \ - CLOSE_TRY_L(L); \ +#define FINALLY_L(L) \ + goto CPP_CONCAT(__FINALLY, L); \ + } \ + CPP_CONCAT(__FINALLY, L) \ + : /* has TRY clause ended without nested throw ? */ \ + if (try_context_get() == &__try##L) \ + { \ + /* restore previous context manually (as a throw would have when caught) */ \ + CLOSE_TRY_L(L); \ } // ----------------------------------------------------------------------- // - CLOSE TRY @@ -114,21 +127,19 @@ SUDOCALL try_context_t* try_context_set(try_context_t *context); /** * Forced finally like clause. */ -#define CLOSE_TRY_L(L) \ - try_context_set(__try ## L.previous) - +#define CLOSE_TRY_L(L) try_context_set(__try##L.previous) // ----------------------------------------------------------------------- // - END TRY // ----------------------------------------------------------------------- -#define END_TRY_L(L) \ - /* nested throw not consumed ? (by CATCH* clause) */ \ - if (__try ## L.ex != 0) { \ - /* rethrow */ \ - THROW_L(L, __try ## L.ex); \ - } \ - } \ - _Static_assert(true, "") +#define END_TRY_L(L) \ + /* nested throw not consumed ? (by CATCH* clause) */ \ + if (__try##L.ex != 0) { \ + /* rethrow */ \ + THROW_L(L, __try##L.ex); \ + } \ + } \ + _Static_assert(true, "") // ----------------------------------------------------------------------- // - EXCEPTION THROW @@ -144,9 +155,9 @@ SUDOCALL try_context_t* try_context_set(try_context_t *context); opened BEGIN/END block. To detect those potential problems, here is a basic sed based script to narrow down the search to potentially suspicious cases. - for i in `find . -name "*.c"`; do echo $i ; sed -n '/BEGIN_TRY/,/END_TRY/{ /goto/{=;H;g;p} ;/return/{=;H;g;p} ; /continue/{=;H;g;p} ; /break/{=;H;g;p} ; h }' $i ; done - Run it on your source code if unsure. - The rule of thumb to respect to decide whether or not to use the CLOSE_TRY + for i in `find . -name "*.c"`; do echo $i ; sed -n '/BEGIN_TRY/,/END_TRY/{ /goto/{=;H;g;p} + ;/return/{=;H;g;p} ; /continue/{=;H;g;p} ; /break/{=;H;g;p} ; h }' $i ; done Run it on your source + code if unsure. The rule of thumb to respect to decide whether or not to use the CLOSE_TRY statement is the following: Jumping out of a TRY/CATCH/CATCH_ALL/CATCH_OTHER clause is not closing the BEGIN/TRY block if the FINALLY is not entirely executed (jumping to a label @@ -337,16 +348,15 @@ void os_longjmp(unsigned int exception) __attribute__((analyzer_noreturn)); #else void os_longjmp(unsigned int exception) __attribute__((noreturn)); #endif -#define THROW_L(L, x) \ - os_longjmp(x) +#define THROW_L(L, x) os_longjmp(x) // Default macros when nesting is not used. -#define THROW(x) THROW_L(EX,x) -#define BEGIN_TRY BEGIN_TRY_L(EX) -#define TRY TRY_L(EX) -#define CATCH(x) CATCH_L(EX,x) -#define CATCH_OTHER(e) CATCH_OTHER_L(EX,e) -#define CATCH_ALL CATCH_ALL_L(EX) -#define FINALLY FINALLY_L(EX) -#define CLOSE_TRY CLOSE_TRY_L(EX) -#define END_TRY END_TRY_L(EX) +#define THROW(x) THROW_L(EX, x) +#define BEGIN_TRY BEGIN_TRY_L(EX) +#define TRY TRY_L(EX) +#define CATCH(x) CATCH_L(EX, x) +#define CATCH_OTHER(e) CATCH_OTHER_L(EX, e) +#define CATCH_ALL CATCH_ALL_L(EX) +#define FINALLY FINALLY_L(EX) +#define CLOSE_TRY CLOSE_TRY_L(EX) +#define END_TRY END_TRY_L(EX) diff --git a/include/ledger_protocol.h b/include/ledger_protocol.h index 15aa57cab..f564252d4 100644 --- a/include/ledger_protocol.h +++ b/include/ledger_protocol.h @@ -1,20 +1,20 @@ /******************************************************************************* -* Ledger Nano S - Secure firmware -* (c) 2022 Ledger -* -* Licensed under the Apache License, Version 2.0 (the "License"); -* you may not use this file except in compliance with the License. -* You may obtain a copy of the License at -* -* http://www.apache.org/licenses/LICENSE-2.0 -* -* Unless required by applicable law or agreed to in writing, software -* distributed under the License is distributed on an "AS IS" BASIS, -* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -* See the License for the specific language governing permissions and -* limitations under the License. -********************************************************************************/ + * Ledger Nano S - Secure firmware + * (c) 2022 Ledger + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + ********************************************************************************/ #pragma once @@ -23,30 +23,30 @@ /* Exported enumerations -----------------------------------------------------*/ enum { - APDU_STATUS_WAITING, - APDU_STATUS_NEED_MORE_DATA, - APDU_STATUS_COMPLETE, + APDU_STATUS_WAITING, + APDU_STATUS_NEED_MORE_DATA, + APDU_STATUS_COMPLETE, }; /* Exported types, structures, unions ----------------------------------------*/ typedef struct ledger_protocol_s { - uint8_t *tx_apdu_buffer; - uint16_t tx_apdu_length; - uint16_t tx_apdu_sequence_number; - uint16_t tx_apdu_offset; - - uint8_t tx_chunk[156+2]; - uint8_t tx_chunk_length; - - uint8_t *rx_apdu_buffer; - uint16_t rx_apdu_buffer_max_length; - uint8_t rx_apdu_status; - uint16_t rx_apdu_sequence_number; - uint16_t rx_apdu_length; - uint16_t rx_apdu_offset; - - uint16_t mtu; - uint8_t mtu_negotiated; + uint8_t *tx_apdu_buffer; + uint16_t tx_apdu_length; + uint16_t tx_apdu_sequence_number; + uint16_t tx_apdu_offset; + + uint8_t tx_chunk[156 + 2]; + uint8_t tx_chunk_length; + + uint8_t *rx_apdu_buffer; + uint16_t rx_apdu_buffer_max_length; + uint8_t rx_apdu_status; + uint16_t rx_apdu_sequence_number; + uint16_t rx_apdu_length; + uint16_t rx_apdu_offset; + + uint16_t mtu; + uint8_t mtu_negotiated; } ledger_protocol_t; /* Exported defines --------------------------------------------------------*/ @@ -57,7 +57,5 @@ typedef struct ledger_protocol_s { /* Exported functions prototypes--------------------------------------------- */ void LEDGER_PROTOCOL_init(ledger_protocol_t *data); -void LEDGER_PROTOCOL_rx(uint8_t *buffer, - uint16_t length); -void LEDGER_PROTOCOL_tx(uint8_t *buffer, - uint16_t length); +void LEDGER_PROTOCOL_rx(uint8_t *buffer, uint16_t length); +void LEDGER_PROTOCOL_tx(uint8_t *buffer, uint16_t length); diff --git a/include/os.h b/include/os.h index 4023b6364..0a6ae4d9d 100644 --- a/include/os.h +++ b/include/os.h @@ -1,20 +1,20 @@ /******************************************************************************* -* Ledger Nano S - Secure firmware -* (c) 2022 Ledger -* -* Licensed under the Apache License, Version 2.0 (the "License"); -* you may not use this file except in compliance with the License. -* You may obtain a copy of the License at -* -* http://www.apache.org/licenses/LICENSE-2.0 -* -* Unless required by applicable law or agreed to in writing, software -* distributed under the License is distributed on an "AS IS" BASIS, -* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -* See the License for the specific language governing permissions and -* limitations under the License. -********************************************************************************/ + * Ledger Nano S - Secure firmware + * (c) 2022 Ledger + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT 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 OS_H #define OS_H @@ -74,9 +74,9 @@ /* - SYSCALL CRYPTO EXPORT - */ /* ----------------------------------------------------------------------- */ -#define CXPORT_ED_DES 0x0001UL -#define CXPORT_ED_AES 0x0002UL -#define CXPORT_ED_RSA 0x0004UL +#define CXPORT_ED_DES 0x0001UL +#define CXPORT_ED_AES 0x0002UL +#define CXPORT_ED_RSA 0x0004UL /* ----------------------------------------------------------------------- */ /* - ENTRY POINT - */ @@ -89,7 +89,8 @@ void app_main(void); void os_boot(void); /** - * Function takes 0 for first call. Returns 0 when timeout has occurred. Returned value is passed as argument for next call, acting as a timeout context. + * Function takes 0 for first call. Returns 0 when timeout has occurred. Returned value is passed as + * argument for next call, acting as a timeout context. */ unsigned short io_timeout(unsigned short last_timeout); @@ -104,34 +105,35 @@ unsigned short io_timeout(unsigned short last_timeout); /* ----------------------------------------------------------------------- */ #include "errors.h" - /** - BOLOS RAM LAYOUT - msp psp psp - | bolos ram <-os stack-| bolos ux ram <-ux_stack-| app ram <-app stack-| +/** +BOLOS RAM LAYOUT + msp psp psp +| bolos ram <-os stack-| bolos ux ram <-ux_stack-| app ram <-app stack-| - ux and app are seen as applications. - os is not an application (it calls ux upon user inputs) +ux and app are seen as applications. +os is not an application (it calls ux upon user inputs) **/ /* ----------------------------------------------------------------------- */ /* - DEBUG FUNCTIONS - */ /* ----------------------------------------------------------------------- */ #ifdef HAVE_PRINTF -void screen_printf(const char* format, ...); -void mcu_usb_printf(const char* format, ...); -#else // !HAVE_PRINTF +void screen_printf(const char *format, ...); +void mcu_usb_printf(const char *format, ...); +#else // !HAVE_PRINTF #define PRINTF(...) -#endif // !HAVE_PRINTF +#endif // !HAVE_PRINTF // redefined if string.h not included #ifdef HAVE_SPRINTF #ifndef __APPLE__ -int snprintf(char * str, size_t str_size, const char * format, ...); -#endif //APPLE -#endif // HAVE_SPRINTF +int snprintf(char *str, size_t str_size, const char *format, ...); +#endif // APPLE +#endif // HAVE_SPRINTF // syscall test -//SYSCALL void dummy_1(unsigned int* p PLENGTH(2+len+15+ len + 16 + sizeof(io_send_t) + 1 ), unsigned int len); +// SYSCALL void dummy_1(unsigned int* p PLENGTH(2+len+15+ len + 16 + sizeof(io_send_t) + 1 ), +// unsigned int len); /* ----------------------------------------------------------------------- */ /* - I/O I2C - */ @@ -143,17 +145,22 @@ int snprintf(char * str, size_t str_size, const char * format, ...); #define IO_I2C_SPEED_FAST 1 #define IO_I2C_SPEED_FASTPLUS 2 #define IO_I2C_SPEED_HS 3 -#define IO_I2C_MASTER 0x80 +#define IO_I2C_MASTER 0x80 /** * Configure the I2C peripheral. - * @param speed_and_master enables to set the bus speed. And to select if the peripheral will act as master (issuing Start and Stop condition upon need) or slave mode. - * @param address In master mode, this parameter sets the target I2C device's address. In slave mode, the address is the desired I2C bus address for the interface. The address is always a 7bit address (excluding the transfer direction bit). + * @param speed_and_master enables to set the bus speed. And to select if the peripheral will act as + * master (issuing Start and Stop condition upon need) or slave mode. + * @param address In master mode, this parameter sets the target I2C device's address. In slave + * mode, the address is the desired I2C bus address for the interface. The address is always a 7bit + * address (excluding the transfer direction bit). */ SYSCALL void io_i2c_setmode(unsigned int speed_and_master, unsigned int address); /** * Setup the I2C peripheral for: - * - In slave mode, receiving a WRITE transaction of maxlength bytes at most. Upon WRITE transaction end, an SEPROXYHAL_TAG_I2C_EVENT is issued with the received data. It has to be received through ::io_seph_recv. + * - In slave mode, receiving a WRITE transaction of maxlength bytes at most. Upon WRITE transaction + * end, an SEPROXYHAL_TAG_I2C_EVENT is issued with the received data. It has to be received through + * ::io_seph_recv. * - In master mode, this call is nop. */ SYSCALL void io_i2c_prepare(unsigned int maxlength); @@ -164,18 +171,23 @@ SYSCALL void io_i2c_prepare(unsigned int maxlength); #define IO_I2C_FLAGS_STOP 4 /** * Request to execute a transfer: - * - In slave mode, this call is non-blocking. It only enables to reply to a READ transaction of at most length bytes. After the Stop condition is issued from the master, a SEPROXYHAL_TAG_I2C_EVENT event containing the effectively transferred length is issued and can be retrieved through ::io_seph_recv. To restart or continue the transfer requires another call to ::io_i2c_xfer. - * - In master mode, this call is blocking and triggers the transaction as requested through the flags parameter. The READ or WRITE transaction will place or transmit data from the given buffer and length. Depending on the passed start/stop flags, corresponding bus condition are executed. + * - In slave mode, this call is non-blocking. It only enables to reply to a READ transaction of at + * most length bytes. After the Stop condition is issued from the master, a SEPROXYHAL_TAG_I2C_EVENT + * event containing the effectively transferred length is issued and can be retrieved through + * ::io_seph_recv. To restart or continue the transfer requires another call to ::io_i2c_xfer. + * - In master mode, this call is blocking and triggers the transaction as requested through the + * flags parameter. The READ or WRITE transaction will place or transmit data from the given buffer + * and length. Depending on the passed start/stop flags, corresponding bus condition are executed. */ -SYSCALL void io_i2c_xfer(void* buffer PLENGTH(length), unsigned int length, unsigned int flags); +SYSCALL void io_i2c_xfer(void *buffer PLENGTH(length), unsigned int length, unsigned int flags); #ifndef BOLOS_RELEASE #ifdef BOLOS_DEBUG SYSCALL void io_i2c_dumpstate(void); -SYSCALL void io_debug(char* chars, unsigned int len); -#endif // BOLOS_DEBUG -#endif // BOLOS_RELEASE +SYSCALL void io_debug(char *chars, unsigned int len); +#endif // BOLOS_DEBUG +#endif // BOLOS_RELEASE -#endif // HAVE_IO_I2C +#endif // HAVE_IO_I2C -#endif // OS_H +#endif // OS_H diff --git a/include/os_apdu.h b/include/os_apdu.h index 54a42c732..42aa0fde8 100644 --- a/include/os_apdu.h +++ b/include/os_apdu.h @@ -5,9 +5,9 @@ /* ----------------------------------------------------------------------- */ // Offsets within the APDU buffer. -#define APDU_OFF_CLA 0 -#define APDU_OFF_INS 1 -#define APDU_OFF_P1 2 -#define APDU_OFF_P2 3 -#define APDU_OFF_LC 4 -#define APDU_OFF_DATA 5 +#define APDU_OFF_CLA 0 +#define APDU_OFF_INS 1 +#define APDU_OFF_P1 2 +#define APDU_OFF_P2 3 +#define APDU_OFF_LC 4 +#define APDU_OFF_DATA 5 diff --git a/include/os_apilevel.h b/include/os_apilevel.h index 6ff16b6de..fce683e0e 100644 --- a/include/os_apilevel.h +++ b/include/os_apilevel.h @@ -1,25 +1,25 @@ /******************************************************************************* -* Ledger Nano S - Secure firmware -* (c) 2022 Ledger -* -* Licensed under the Apache License, Version 2.0 (the "License"); -* you may not use this file except in compliance with the License. -* You may obtain a copy of the License at -* -* http://www.apache.org/licenses/LICENSE-2.0 -* -* Unless required by applicable law or agreed to in writing, software -* distributed under the License is distributed on an "AS IS" BASIS, -* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -* See the License for the specific language governing permissions and -* limitations under the License. -********************************************************************************/ + * Ledger Nano S - Secure firmware + * (c) 2022 Ledger + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT 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 OS_APILEVEL_H #define OS_APILEVEL_H -#define CX_APILEVEL 12 +#define CX_APILEVEL 12 #define CX_COMPAT_APILEVEL 12 -#endif // OS_APILEVEL_H +#endif // OS_APILEVEL_H diff --git a/include/os_app.h b/include/os_app.h index 63625905c..7cd2fcd4e 100644 --- a/include/os_app.h +++ b/include/os_app.h @@ -10,54 +10,58 @@ /* - APPLICATION FUNCTIONS - */ /* ----------------------------------------------------------------------- */ -typedef void (*appmain_t) (void); +typedef void (*appmain_t)(void); -#define BOLOS_TAG_APPNAME 0x01 +#define BOLOS_TAG_APPNAME 0x01 #define BOLOS_TAG_APPVERSION 0x02 -#define BOLOS_TAG_ICON 0x03 +#define BOLOS_TAG_ICON 0x03 #define BOLOS_TAG_DERIVEPATH 0x04 -#define BOLOS_TAG_DATA_SIZE 0x05 // meta tag to retrieve the size of the data section for the application -// Library Dependencies are a tuple of 2 LV, the lib appname and the lib version (only exact for now). When lib version is not specified, it is not check, only name is asserted -// The DEPENDENCY tag may have several occurrences, one for each dependency (by name). Malformed (multiple dep to the same lib with different version is is not ORed but ANDed, and then considered bogus) +#define BOLOS_TAG_DATA_SIZE \ + 0x05 // meta tag to retrieve the size of the data section for the application +// Library Dependencies are a tuple of 2 LV, the lib appname and the lib version (only exact for +// now). When lib version is not specified, it is not check, only name is asserted The DEPENDENCY +// tag may have several occurrences, one for each dependency (by name). Malformed (multiple dep to +// the same lib with different version is is not ORed but ANDed, and then considered bogus) #define BOLOS_TAG_DEPENDENCY 0x06 // first autorised tag value for user data -#define BOLOS_TAG_USER_TAG 0x20 +#define BOLOS_TAG_USER_TAG 0x20 // application slot description typedef struct application_s { + // nvram start address for this application (to check overlap when loading, and mpu lock) + unsigned char *nvram_begin; + // nvram stop address (exclusive) for this application (to check overlap when loading, and mpu + // lock) + unsigned char *nvram_end; - // nvram start address for this application (to check overlap when loading, and mpu lock) - unsigned char * nvram_begin; - // nvram stop address (exclusive) for this application (to check overlap when loading, and mpu lock) - unsigned char * nvram_end; - - // address of the main address, must be set according to BLX spec ( ORed with 1 when jumping into Thumb code - appmain_t main; + // address of the main address, must be set according to BLX spec ( ORed with 1 when jumping + // into Thumb code + appmain_t main; #ifdef HAVE_BACKGROUND_IMG - // special flags for this application - uint64_t flags; + // special flags for this application + uint64_t flags; #else - // special flags for this application - uint32_t flags; + // special flags for this application + uint32_t flags; #endif - // Memory organization: [ code (RX) |alignpage| data (RW) |alignpage| install params (R) ] + // Memory organization: [ code (RX) |alignpage| data (RW) |alignpage| install params (R) ] - // length of the code section of the application (RX) - unsigned int code_length; + // length of the code section of the application (RX) + unsigned int code_length; - // NOTE: code_length+params_length must be a multiple of PAGE_SIZE - // Length of the DATA section of the application. (RW) - unsigned int data_length; + // NOTE: code_length+params_length must be a multiple of PAGE_SIZE + // Length of the DATA section of the application. (RW) + unsigned int data_length; - // NOTE: code_length+params_length must be a multiple of PAGE_SIZE - // length of the parameters sections of the application (R) - unsigned int params_length; + // NOTE: code_length+params_length must be a multiple of PAGE_SIZE + // length of the parameters sections of the application (R) + unsigned int params_length; - // Intermediate hash of the application's loaded code and data segments - unsigned char sha256_code_data[32]; - // Hash of the application's loaded code, data and instantiation parameters - unsigned char sha256_full[32]; + // Intermediate hash of the application's loaded code and data segments + unsigned char sha256_code_data[32]; + // Hash of the application's loaded code, data and instantiation parameters + unsigned char sha256_full[32]; } application_t; diff --git a/include/os_customca.h b/include/os_customca.h index 3066f69c9..2104e86da 100644 --- a/include/os_customca.h +++ b/include/os_customca.h @@ -9,5 +9,7 @@ /* ----------------------------------------------------------------------- */ // Verify the signature is issued from the custom certificate authority -SYSCALL unsigned int os_customca_verify(unsigned char* hash PLENGTH(32), unsigned char* sign PLENGTH(sign_length), unsigned int sign_length); -#endif // HAVE_BOLOS_NO_CUSTOMCA +SYSCALL unsigned int os_customca_verify(unsigned char *hash PLENGTH(32), + unsigned char *sign PLENGTH(sign_length), + unsigned int sign_length); +#endif // HAVE_BOLOS_NO_CUSTOMCA diff --git a/include/os_debug.h b/include/os_debug.h index 1ac542db0..75a5f59bf 100644 --- a/include/os_debug.h +++ b/include/os_debug.h @@ -4,8 +4,8 @@ #include "decorators.h" #ifdef DEBUG_OS_STACK_CONSUMPTION -#define MODE_INITIALIZATION 0x00 -#define MODE_RETRIEVAL 0x01 +#define MODE_INITIALIZATION 0x00 +#define MODE_RETRIEVAL 0x01 /** * Debug syscall allowing one to monitor the OS stack usage of other syscalls. * This syscall cannot be embedded within the release version of the OS. @@ -20,4 +20,4 @@ * stack. */ SYSCALL int os_stack_operations(unsigned char mode); -#endif // DEBUG_OS_STACK_CONSUMPTION +#endif // DEBUG_OS_STACK_CONSUMPTION diff --git a/include/os_endorsement.h b/include/os_endorsement.h index ef0cda5e5..34b286a62 100644 --- a/include/os_endorsement.h +++ b/include/os_endorsement.h @@ -14,16 +14,28 @@ typedef enum endorsement_revoke_id_e { ENDORSEMENT_REVOKE_ID_LAST = 3, } endorsement_revoke_id_t; -#define ENDORSEMENT_MAX_ASN1_LENGTH (1 + 1 + 2 * (1 + 1 + 33)) +#define ENDORSEMENT_MAX_ASN1_LENGTH (1 + 1 + 2 * (1 + 1 + 33)) -SYSCALL unsigned int os_endorsement_get_code_hash(unsigned char* buffer PLENGTH(32)); -SYSCALL unsigned int os_endorsement_get_public_key(unsigned char index, unsigned char* buffer PLENGTH(65), unsigned char *length PLENGTH(1)); -SYSCALL unsigned int os_endorsement_get_public_key_certificate(unsigned char index, unsigned char* buffer PLENGTH(ENDORSEMENT_MAX_ASN1_LENGTH), unsigned char* length PLENGTH(1)); -SYSCALL unsigned int os_endorsement_key1_get_app_secret(unsigned char* buffer PLENGTH(64)); -SYSCALL unsigned int os_endorsement_key1_sign_data(unsigned char* src PLENGTH(srcLength), unsigned int srcLength, unsigned char* signature PLENGTH(ENDORSEMENT_MAX_ASN1_LENGTH)); -SYSCALL unsigned int os_endorsement_key2_derive_sign_data(unsigned char* src PLENGTH(srcLength), unsigned int srcLength, unsigned char* signature PLENGTH(ENDORSEMENT_MAX_ASN1_LENGTH)); +SYSCALL unsigned int os_endorsement_get_code_hash(unsigned char *buffer PLENGTH(32)); +SYSCALL unsigned int os_endorsement_get_public_key(unsigned char index, + unsigned char *buffer PLENGTH(65), + unsigned char *length PLENGTH(1)); +SYSCALL unsigned int os_endorsement_get_public_key_certificate( + unsigned char index, + unsigned char *buffer PLENGTH(ENDORSEMENT_MAX_ASN1_LENGTH), + unsigned char *length PLENGTH(1)); +SYSCALL unsigned int os_endorsement_key1_get_app_secret(unsigned char *buffer PLENGTH(64)); +SYSCALL unsigned int os_endorsement_key1_sign_data(unsigned char *src PLENGTH(srcLength), + unsigned int srcLength, + unsigned char *signature + PLENGTH(ENDORSEMENT_MAX_ASN1_LENGTH)); +SYSCALL unsigned int os_endorsement_key2_derive_sign_data(unsigned char *src PLENGTH(srcLength), + unsigned int srcLength, + unsigned char *signature + PLENGTH(ENDORSEMENT_MAX_ASN1_LENGTH)); -SYSCALL unsigned int os_endorsement_get_metadata(unsigned char index, unsigned char* buffer PLENGTH(8)); +SYSCALL unsigned int os_endorsement_get_metadata(unsigned char index, + unsigned char *buffer PLENGTH(8)); SYSCALL void os_endorsement_revoke_slot1(void); SYSCALL void os_endorsement_revoke_slot2(void); diff --git a/include/os_hal_arm_v6v7m_dummy.h b/include/os_hal_arm_v6v7m_dummy.h index bd41e2fc6..09f264727 100644 --- a/include/os_hal_arm_v6v7m_dummy.h +++ b/include/os_hal_arm_v6v7m_dummy.h @@ -1,20 +1,20 @@ /******************************************************************************* -* Ledger Nano S - Secure firmware -* (c) 2022 Ledger -* -* Licensed under the Apache License, Version 2.0 (the "License"); -* you may not use this file except in compliance with the License. -* You may obtain a copy of the License at -* -* http://www.apache.org/licenses/LICENSE-2.0 -* -* Unless required by applicable law or agreed to in writing, software -* distributed under the License is distributed on an "AS IS" BASIS, -* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -* See the License for the specific language governing permissions and -* limitations under the License. -********************************************************************************/ + * Ledger Nano S - Secure firmware + * (c) 2022 Ledger + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + ********************************************************************************/ #pragma once diff --git a/include/os_helpers.h b/include/os_helpers.h index 21fe7f653..f4f92fd90 100644 --- a/include/os_helpers.h +++ b/include/os_helpers.h @@ -7,10 +7,14 @@ #define OS_PARSE_BERTLV_OFFSET_COMPARE_WITH_BUFFER 0x80000000UL #define OS_PARSE_BERTLV_OFFSET_GET_LENGTH 0x40000000UL -unsigned int os_parse_bertlv(unsigned char* mem, unsigned int mem_len, - unsigned int * tlv_instance_offset, - unsigned int tag, unsigned int offset, void** buffer, unsigned int maxlength); +unsigned int os_parse_bertlv(unsigned char *mem, + unsigned int mem_len, + unsigned int *tlv_instance_offset, + unsigned int tag, + unsigned int offset, + void **buffer, + unsigned int maxlength); #ifndef UNUSED -#define UNUSED(x) (void)x -#endif +#define UNUSED(x) (void) x +#endif diff --git a/include/os_id.h b/include/os_id.h index e9abd69c6..791fff86e 100644 --- a/include/os_id.h +++ b/include/os_id.h @@ -16,38 +16,43 @@ #define OS_FLAG_HSM_INITIALIZED (1 << 5) #define OS_FLAG_FACTORY_FILLED (1 << 6) #define OS_FLAG_PIN_VALIDATED (1 << 7) -//#define OS_FLAG_CUSTOM_UX 4 +// #define OS_FLAG_CUSTOM_UX 4 /* Enable application to retrieve OS current running options */ SYSCALL unsigned int os_flags(void); - SYSCALL unsigned int os_version(unsigned char* version PLENGTH(maxlength), unsigned int maxlength); +SYSCALL unsigned int os_version(unsigned char *version PLENGTH(maxlength), unsigned int maxlength); /* Grab the SE serial number */ - SYSCALL unsigned int os_serial(unsigned char* serial PLENGTH(maxlength), unsigned int maxlength); +SYSCALL unsigned int os_serial(unsigned char *serial PLENGTH(maxlength), unsigned int maxlength); #ifdef HAVE_MCU_SERIAL_STORAGE /* Grab the SEPROXYHAL's MCU serial number */ - SYSCALL unsigned int os_seph_serial(unsigned char* serial PLENGTH(maxlength), unsigned int maxlength); -#endif // HAVE_MCU_SERIAL_STORAGE -/* Grab the SEPROXYHAL's feature set */ - SYSCALL unsigned int os_seph_features(void); +SYSCALL unsigned int os_seph_serial(unsigned char *serial PLENGTH(maxlength), + unsigned int maxlength); +#endif // HAVE_MCU_SERIAL_STORAGE + /* Grab the SEPROXYHAL's feature set */ +SYSCALL unsigned int os_seph_features(void); /* Grab the SEPROXYHAL's version */ - SYSCALL unsigned int os_seph_version(unsigned char* version PLENGTH(maxlength), unsigned int maxlength); +SYSCALL unsigned int os_seph_version(unsigned char *version PLENGTH(maxlength), + unsigned int maxlength); /* Grab the MCU bootloader's version */ - SYSCALL unsigned int os_bootloader_version(unsigned char* version PLENGTH(maxlength), unsigned int maxlength); +SYSCALL unsigned int os_bootloader_version(unsigned char *version PLENGTH(maxlength), + unsigned int maxlength); /* Grab factory setting */ - SYSCALL unsigned int os_factory_setting_get(unsigned int id, unsigned char* value PLENGTH(maxlength), unsigned int maxlength); - +SYSCALL unsigned int os_factory_setting_get(unsigned int id, + unsigned char *value PLENGTH(maxlength), + unsigned int maxlength); /* * Copy the serial number in the given buffer and return its length */ - unsigned int os_get_sn(unsigned char* buffer); +unsigned int os_get_sn(unsigned char *buffer); // get API level SYSCALL unsigned int get_api_level(void); #ifndef HAVE_BOLOS -static inline void check_api_level(unsigned int apiLevel) { - if (apiLevel < get_api_level()) { - os_sched_exit(-1); - } +static inline void check_api_level(unsigned int apiLevel) +{ + if (apiLevel < get_api_level()) { + os_sched_exit(-1); + } } #endif diff --git a/include/os_io.h b/include/os_io.h index 4249aa067..8cc98900c 100644 --- a/include/os_io.h +++ b/include/os_io.h @@ -10,9 +10,9 @@ // the global apdu buffer #ifdef HAVE_IO_U2F -#define IMPL_IO_APDU_BUFFER_SIZE (3+32+32+15+255) +#define IMPL_IO_APDU_BUFFER_SIZE (3 + 32 + 32 + 15 + 255) #else -#define IMPL_IO_APDU_BUFFER_SIZE (5+255) +#define IMPL_IO_APDU_BUFFER_SIZE (5 + 255) #endif #ifdef CUSTOM_IO_APDU_BUFFER_SIZE #define IO_APDU_BUFFER_SIZE MAX(IMPL_IO_APDU_BUFFER_SIZE, CUSTOM_IO_APDU_BUFFER_SIZE) @@ -21,34 +21,34 @@ #endif typedef struct apdu_buffer_s { - uint8_t * buf; - uint16_t len; + uint8_t *buf; + uint16_t len; } apdu_buffer_t; extern unsigned char G_io_apdu_buffer[IO_APDU_BUFFER_SIZE]; -// send tx_len bytes (atr or rapdu) and retrieve the length of the next command apdu (over the requested channel) -#define CHANNEL_APDU 0 -#define CHANNEL_KEYBOARD 1 -#define CHANNEL_SPI 2 +// send tx_len bytes (atr or rapdu) and retrieve the length of the next command apdu (over the +// requested channel) +#define CHANNEL_APDU 0 +#define CHANNEL_KEYBOARD 1 +#define CHANNEL_SPI 2 #define IO_RESET_AFTER_REPLIED 0x80 -#define IO_RECEIVE_DATA 0x40 -#define IO_RETURN_AFTER_TX 0x20 -#define IO_ASYNCH_REPLY 0x10 // avoid apdu state reset if tx_len == 0 when we're expected to reply -#define IO_FINISHED 0x08 // inter task communication value -#define IO_FLAGS 0xF8 +#define IO_RECEIVE_DATA 0x40 +#define IO_RETURN_AFTER_TX 0x20 +#define IO_ASYNCH_REPLY 0x10 // avoid apdu state reset if tx_len == 0 when we're expected to reply +#define IO_FINISHED 0x08 // inter task communication value +#define IO_FLAGS 0xF8 unsigned short io_exchange(unsigned char channel_and_flags, unsigned short tx_len); - typedef enum { - IO_APDU_MEDIA_NONE = 0, // not correctly in an apdu exchange - IO_APDU_MEDIA_USB_HID = 1, - IO_APDU_MEDIA_BLE, - IO_APDU_MEDIA_NFC, - IO_APDU_MEDIA_USB_CCID, - IO_APDU_MEDIA_USB_WEBUSB, - IO_APDU_MEDIA_RAW, - IO_APDU_MEDIA_U2F, + IO_APDU_MEDIA_NONE = 0, // not correctly in an apdu exchange + IO_APDU_MEDIA_USB_HID = 1, + IO_APDU_MEDIA_BLE, + IO_APDU_MEDIA_NFC, + IO_APDU_MEDIA_USB_CCID, + IO_APDU_MEDIA_USB_WEBUSB, + IO_APDU_MEDIA_RAW, + IO_APDU_MEDIA_U2F, } io_apdu_media_t; #ifndef USB_SEGMENT_SIZE @@ -67,36 +67,38 @@ extern unsigned char G_io_usb_ep_buffer[MAX(USB_SEGMENT_SIZE, BLE_SEGMENT_SIZE)] /** * Return 1 when the event has been processed, 0 else */ -// io callback in the application called when an interrupt based channel has received data to be processed +// io callback in the application called when an interrupt based channel has received data to be +// processed unsigned char io_event(unsigned char channel); #ifdef HAVE_SE_TOUCH typedef struct io_touch_info_s { uint16_t x; uint16_t y; - uint8_t state; - uint8_t w; - uint8_t h; + uint8_t state; + uint8_t w; + uint8_t h; } io_touch_info_t; typedef enum io_touch_debug_mode_e { - TOUCH_DEBUG_END = 0, - TOUCH_DEBUG_READ_RAW_DATA = 1, + TOUCH_DEBUG_END = 0, + TOUCH_DEBUG_READ_RAW_DATA = 1, TOUCH_DEBUG_READ_DIFF_DATA = 2, } io_touch_debug_mode_t; -// bitfield for exclusion borders, for touch_exclude_borders() (if a bit is set, means that pixels on this border are not taken into account) +// bitfield for exclusion borders, for touch_exclude_borders() (if a bit is set, means that pixels +// on this border are not taken into account) #define LEFT_BORDER 1 #define RIGHT_BORDER 2 #define TOP_BORDER 4 #define BOTTOM_BORDER 8 #ifdef HAVE_SE_TOUCH -SYSCALL void touch_get_last_info(io_touch_info_t *info); -SYSCALL void touch_set_state(bool enable); +SYSCALL void touch_get_last_info(io_touch_info_t *info); +SYSCALL void touch_set_state(bool enable); SYSCALL uint8_t touch_exclude_borders(uint8_t excluded_borders); #ifdef HAVE_TOUCH_READ_DEBUG_DATA_SYSCALL SYSCALL uint8_t touch_switch_debug_mode_and_read(io_touch_debug_mode_t mode, uint8_t *read_buffer); #endif #endif -#endif // HAVE_SE_TOUCH +#endif // HAVE_SE_TOUCH diff --git a/include/os_io_seproxyhal.h b/include/os_io_seproxyhal.h index e43ce042a..83d236e22 100644 --- a/include/os_io_seproxyhal.h +++ b/include/os_io_seproxyhal.h @@ -1,27 +1,27 @@ /******************************************************************************* -* Ledger Nano S - Secure firmware -* (c) 2022 Ledger -* -* Licensed under the Apache License, Version 2.0 (the "License"); -* you may not use this file except in compliance with the License. -* You may obtain a copy of the License at -* -* http://www.apache.org/licenses/LICENSE-2.0 -* -* Unless required by applicable law or agreed to in writing, software -* distributed under the License is distributed on an "AS IS" BASIS, -* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -* See the License for the specific language governing permissions and -* limitations under the License. -********************************************************************************/ + * Ledger Nano S - Secure firmware + * (c) 2022 Ledger + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT 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 OS_IO_SEPROXYHAL_H #define OS_IO_SEPROXYHAL_H #if defined(HAVE_BOLOS) -# include "bolos_privileged_ux.h" -#endif // HAVE_BOLOS +#include "bolos_privileged_ux.h" +#endif // HAVE_BOLOS #include "bolos_target.h" #include "decorators.h" @@ -45,23 +45,31 @@ #include "seproxyhal_protocol.h" // helper macro to swap values, without intermediate value -#define SWAP(a,b) {a ^= b ; b ^= a ; a ^= b;} +#define SWAP(a, b) \ + { \ + a ^= b; \ + b ^= a; \ + a ^= b; \ + } extern unsigned char G_io_seproxyhal_spi_buffer[IO_SEPROXYHAL_BUFFER_SIZE_B]; -SYSCALL void io_seph_send(const unsigned char * buffer PLENGTH(length), unsigned short length); +SYSCALL void io_seph_send(const unsigned char *buffer PLENGTH(length), unsigned short length); -// return 1 if the previous seproxyhal exchange has been terminated with a status (packet which starts with 011x xxxx) -// else 0, which means the exchange needs to be closed. +// return 1 if the previous seproxyhal exchange has been terminated with a status (packet which +// starts with 011x xxxx) else 0, which means the exchange needs to be closed. SYSCALL unsigned int io_seph_is_status_sent(void); -// not to be called by application (application is triggered using io_event instead), resered for seproxyhal +// not to be called by application (application is triggered using io_event instead), resered for +// seproxyhal #define IO_CACHE 1 -SYSCALL unsigned short io_seph_recv(unsigned char * buffer PLENGTH(maxlength), unsigned short maxlength, unsigned int flags); +SYSCALL unsigned short io_seph_recv(unsigned char *buffer PLENGTH(maxlength), + unsigned short maxlength, + unsigned int flags); -#define io_seproxyhal_spi_send io_seph_send +#define io_seproxyhal_spi_send io_seph_send #define io_seproxyhal_spi_is_status_sent io_seph_is_status_sent -#define io_seproxyhal_spi_recv io_seph_recv +#define io_seproxyhal_spi_recv io_seph_recv // HAL init, not meant to be called by applications, which shall call ::io_seproxyhal_init instead void io_seph_init(void); @@ -72,21 +80,23 @@ void io_seproxyhal_init(void); // only reinit ux related globals void io_seproxyhal_init_ux(void); -// only init button handling related variables (not to be done when switching screen to avoid the release triggering unwanted behavior) +// only init button handling related variables (not to be done when switching screen to avoid the +// release triggering unwanted behavior) void io_seproxyhal_init_button(void); // delegate function for generic io_exchange unsigned short io_exchange_al(unsigned char channel_and_flags, unsigned short tx_len); -// Allow application to overload how the io_exchange function automatically replies to get app name and version +// Allow application to overload how the io_exchange function automatically replies to get app name +// and version unsigned int os_io_seproxyhal_get_app_name_and_version(void); // for delegation of Native NFC / USB unsigned char io_event(unsigned char channel); #ifdef HAVE_BLE -void BLE_power(unsigned char powered, const char* discovered_name); -#endif // HAVE_BLE +void BLE_power(unsigned char powered, const char *discovered_name); +#endif // HAVE_BLE #ifdef __cplusplus extern "C" void USB_power(unsigned char enabled); @@ -94,8 +104,8 @@ extern "C" void USB_power(unsigned char enabled); void USB_power(unsigned char enabled); #endif -void io_seproxyhal_handle_usb_event(void); -void io_seproxyhal_handle_usb_ep_xfer_event(void); +void io_seproxyhal_handle_usb_event(void); +void io_seproxyhal_handle_usb_ep_xfer_event(void); uint16_t io_seproxyhal_get_ep_rx_size(uint8_t epnum); // process event for io protocols when waiting for a ux operation to end @@ -109,13 +119,16 @@ void io_seproxyhal_general_status(void); void os_io_seproxyhal_general_status_processing(void); // legacy function to send over EP 0x82 -void io_usb_send_apdu_data(unsigned char* buffer, unsigned short length); -void io_usb_send_apdu_data_ep0x83(unsigned char* buffer, unsigned short length); +void io_usb_send_apdu_data(unsigned char *buffer, unsigned short length); +void io_usb_send_apdu_data_ep0x83(unsigned char *buffer, unsigned short length); // trigger a transfer over an usb endpoint and waits for it to occur if timeout is != 0 -void io_usb_send_ep(unsigned int ep, unsigned char* buffer, unsigned short length, unsigned int timeout); +void io_usb_send_ep(unsigned int ep, + unsigned char *buffer, + unsigned short length, + unsigned int timeout); -void io_usb_ccid_reply(unsigned char* buffer, unsigned short length); +void io_usb_ccid_reply(unsigned char *buffer, unsigned short length); #ifdef HAVE_SERIALIZED_NBGL void io_seproxyhal_send_nbgl_serialized(nbgl_serialized_event_type_e event, nbgl_obj_t *obj); @@ -130,41 +143,41 @@ void io_set_timeout(unsigned int timeout); #ifdef HAVE_NFC #ifdef HAVE_NDEF_SUPPORT void io_seproxyhal_nfc_init(ndef_struct_t *ndef_message, bool async, bool forceInit); -#else // ! HAVE_NDEF_SUPPORT +#else // ! HAVE_NDEF_SUPPORT void io_seproxyhal_nfc_init(bool forceInit); -#endif // HAVE_NDEF_SUPPORT +#endif // HAVE_NDEF_SUPPORT #endif #ifdef HAVE_SE_TOUCH #ifdef HAVE_TOUCH_READ_DEBUG_DATA_SYSCALL -bolos_bool_t io_seproxyhal_touch_debug_read_sensi(uint8_t * sensi_data); -bolos_bool_t io_seproxyhal_touch_debug_read_diff_data(uint8_t * sensi_data); +bolos_bool_t io_seproxyhal_touch_debug_read_sensi(uint8_t *sensi_data); +bolos_bool_t io_seproxyhal_touch_debug_read_diff_data(uint8_t *sensi_data); bolos_bool_t io_seproxyhal_touch_debug_end(void); #endif #endif typedef enum { - APDU_IDLE, - APDU_BLE, - APDU_BLE_WAIT_NOTIFY, + APDU_IDLE, + APDU_BLE, + APDU_BLE_WAIT_NOTIFY, #ifdef HAVE_NFC - APDU_NFC, + APDU_NFC, #endif - APDU_NFC_M24SR, - APDU_NFC_M24SR_SELECT, - APDU_NFC_M24SR_FIRST, - APDU_NFC_M24SR_RAPDU, - APDU_USB_HID, - APDU_USB_CCID, - APDU_U2F, - APDU_RAW, - APDU_USB_WEBUSB, + APDU_NFC_M24SR, + APDU_NFC_M24SR_SELECT, + APDU_NFC_M24SR_FIRST, + APDU_NFC_M24SR_RAPDU, + APDU_USB_HID, + APDU_USB_CCID, + APDU_U2F, + APDU_RAW, + APDU_USB_WEBUSB, } io_apdu_state_e; #ifdef HAVE_IO_U2F #include "u2f_service.h" extern u2f_service_t G_io_u2f; -#endif // HAVE_IO_U2F +#endif // HAVE_IO_U2F /** * Ledger Bluetooth Low Energy APDU Protocol @@ -175,14 +188,17 @@ extern u2f_service_t G_io_u2f; * All fields are big endian encoded. * TT: 1 byte content tag * SSSS: 2 bytes sequence number, big endian encoded (start @ 0). - * VVVV..VV: variable length content. When SSSS is 0, the first two bytes encodes in big endian the total length of the APDU to transport. + * VVVV..VV: variable length content. When SSSS is 0, the first two bytes encodes in big endian the + * total length of the APDU to transport. * * Command/Response APDU are split in chunks to fill up the bluetooth's characteristic * - * APDU are using either standard or extended header. up to the application to check the total received length and the lc field + * APDU are using either standard or extended header. up to the application to check the total + * received length and the lc field * * Tags: - * Direction:* T:0x05 S= V= APDU (command/response) packet. + * Direction:* T:0x05 S= V= APDU + * (command/response) packet. * * Example: * -------- @@ -215,41 +231,42 @@ extern u2f_service_t G_io_u2f; * Wait until a UX call returns a definitve status. Handle all event packets in between */ #if !defined(APP_UX) -unsigned int os_ux_blocking(bolos_ux_params_t* params); -#endif // !defined(APP_UX) +unsigned int os_ux_blocking(bolos_ux_params_t *params); +#endif // !defined(APP_UX) /** - * Global type that enables to map memory onto the application zone instead of over the os for os side + * Global type that enables to map memory onto the application zone instead of over the os for os + * side */ typedef struct io_seph_s { - io_apdu_state_e apdu_state; // by default - unsigned short apdu_length; // total length to be received - unsigned short io_flags; // flags to be set when calling io_exchange - io_apdu_media_t apdu_media; + io_apdu_state_e apdu_state; // by default + unsigned short apdu_length; // total length to be received + unsigned short io_flags; // flags to be set when calling io_exchange + io_apdu_media_t apdu_media; - unsigned int ms; + unsigned int ms; #ifdef HAVE_IO_USB - unsigned char usb_ep_xfer_len[IO_USB_MAX_ENDPOINTS]; - struct { - unsigned short timeout; // up to 64k milliseconds (64 sec) - } usb_ep_timeouts[IO_USB_MAX_ENDPOINTS]; -#endif // HAVE_IO_USB + unsigned char usb_ep_xfer_len[IO_USB_MAX_ENDPOINTS]; + struct { + unsigned short timeout; // up to 64k milliseconds (64 sec) + } usb_ep_timeouts[IO_USB_MAX_ENDPOINTS]; +#endif // HAVE_IO_USB #ifdef HAVE_BLE_APDU - unsigned short ble_xfer_timeout; -#endif // HAVE_BLE_APDU + unsigned short ble_xfer_timeout; +#endif // HAVE_BLE_APDU #ifdef HAVE_BLE - // cached here to avoid unavailable zone deref within IO task - unsigned int plane_mode; - unsigned char ble_ready; - unsigned char name_changed; - unsigned char enabling_advertising; - unsigned char disabling_advertising; -#endif // HAVE_BLE - - unsigned char transfer_mode; + // cached here to avoid unavailable zone deref within IO task + unsigned int plane_mode; + unsigned char ble_ready; + unsigned char name_changed; + unsigned char enabling_advertising; + unsigned char disabling_advertising; +#endif // HAVE_BLE + + unsigned char transfer_mode; } io_seph_app_t; extern io_seph_app_t G_io_app; @@ -268,7 +285,7 @@ void io_task(void); * IO task initializez */ void io_start(void); -#endif // HAVE_IO_TASK +#endif // HAVE_IO_TASK void io_seproxyhal_setup_ticker(unsigned int interval_ms); void io_seproxyhal_power_off(bool criticalBattery); @@ -288,22 +305,23 @@ typedef enum tune_index_e { TUNE_LOOK_AT_ME, TUNE_TAP_CASUAL, TUNE_TAP_NEXT, - NB_TUNES // Keep at last position + NB_TUNES // Keep at last position } tune_index_e; void io_seproxyhal_play_tune(tune_index_e tune_index); -#endif // HAVE_PIEZO_SOUND +#endif // HAVE_PIEZO_SOUND #ifdef HAVE_BLE void io_seph_ble_enable(unsigned char enable); void io_seph_ble_clear_bond_db(void); void io_seph_ble_name_changed(void); -#endif // HAVE_BLE +#endif // HAVE_BLE void io_seph_ux_redisplay(void); /** - * Function to ensure a I/O channel is not timeouting waiting for operations after a long time without SEPH packet exchanges + * Function to ensure a I/O channel is not timeouting waiting for operations after a long time + * without SEPH packet exchanges */ void io_seproxyhal_io_heartbeat(void); @@ -312,9 +330,9 @@ unsigned int os_io_seph_recv_and_process(unsigned int dont_process_ux_events); #ifdef HAVE_PRINTF // Sends a character to the MCU and waits for the MCU acknowledgement. -void mcu_usb_prints(const char* str, unsigned int charcount); -#endif // HAVE_PRINTF +void mcu_usb_prints(const char *str, unsigned int charcount); +#endif // HAVE_PRINTF -#endif // OS_IO_SEPROXYHAL +#endif // OS_IO_SEPROXYHAL -#endif // OS_IO_SEPROXYHAL_H +#endif // OS_IO_SEPROXYHAL_H diff --git a/include/os_io_usb.h b/include/os_io_usb.h index 5d928aeee..d9b6d99c2 100644 --- a/include/os_io_usb.h +++ b/include/os_io_usb.h @@ -1,20 +1,20 @@ /******************************************************************************* -* Ledger Nano S - Secure firmware -* (c) 2022 Ledger -* -* Licensed under the Apache License, Version 2.0 (the "License"); -* you may not use this file except in compliance with the License. -* You may obtain a copy of the License at -* -* http://www.apache.org/licenses/LICENSE-2.0 -* -* Unless required by applicable law or agreed to in writing, software -* distributed under the License is distributed on an "AS IS" BASIS, -* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -* See the License for the specific language governing permissions and -* limitations under the License. -********************************************************************************/ + * Ledger Nano S - Secure firmware + * (c) 2022 Ledger + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT 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 OS_IO_USB_H #define OS_IO_USB_H @@ -27,27 +27,28 @@ /* ----------------------------------------------------------------------- */ /* - IO FUNCTIONS - */ /* ----------------------------------------------------------------------- */ -typedef void (*io_send_t)(unsigned char* buffer, unsigned short length); - -typedef unsigned short (*io_recv_t)(unsigned char* buffer, unsigned short maxlenth); +typedef void (*io_send_t)(unsigned char *buffer, unsigned short length); +typedef unsigned short (*io_recv_t)(unsigned char *buffer, unsigned short maxlenth); typedef enum io_usb_hid_receive_status_e { - IO_USB_APDU_RESET, - IO_USB_APDU_MORE_DATA, - IO_USB_APDU_RECEIVED, + IO_USB_APDU_RESET, + IO_USB_APDU_MORE_DATA, + IO_USB_APDU_RECEIVED, } io_usb_hid_receive_status_t; -extern volatile unsigned int G_io_usb_hid_total_length; +extern volatile unsigned int G_io_usb_hid_total_length; void io_usb_hid_init(void); /** - * Receive next HID transport packet, returns IO_USB_APDU_RECEIVED when a complete APDU has been received in the G_io_apdu_buffer - * To be called typically upon USB OUT event + * Receive next HID transport packet, returns IO_USB_APDU_RECEIVED when a complete APDU has been + * received in the G_io_apdu_buffer To be called typically upon USB OUT event */ -io_usb_hid_receive_status_t -io_usb_hid_receive(io_send_t sndfct, unsigned char* buffer, unsigned short l, apdu_buffer_t * apdu_buffer); +io_usb_hid_receive_status_t io_usb_hid_receive(io_send_t sndfct, + unsigned char *buffer, + unsigned short l, + apdu_buffer_t *apdu_buffer); /** * Mark the last chunk transmitted as sent. @@ -58,8 +59,8 @@ void io_usb_hid_sent(io_send_t sndfct); /** * Request transmission of an APDU from the G_io_apdu_buffer using the HID transport protocol */ -void io_usb_hid_send(io_send_t sndfct, unsigned short sndlength, unsigned char * apdu_buffer); +void io_usb_hid_send(io_send_t sndfct, unsigned short sndlength, unsigned char *apdu_buffer); -#endif // HAVE_USB_APDU +#endif // HAVE_USB_APDU #endif diff --git a/include/os_lib.h b/include/os_lib.h index 4025ea498..d60004a32 100644 --- a/include/os_lib.h +++ b/include/os_lib.h @@ -11,7 +11,7 @@ * call_parameters[1] = library call identifier (0 = init, ...) * call_parameters[2+] = called function parameters */ -SYSCALL void os_lib_call(unsigned int *call_parameters PLENGTH(3*sizeof(unsigned int))); +SYSCALL void os_lib_call(unsigned int *call_parameters PLENGTH(3 * sizeof(unsigned int))); #ifdef HAVE_BOLOS SYSCALL void os_lib_end(void); #else diff --git a/include/os_math.h b/include/os_math.h index 49ded5cd4..1f5c152d1 100644 --- a/include/os_math.h +++ b/include/os_math.h @@ -1,10 +1,10 @@ #pragma once #ifndef MIN -#define MIN(x,y) ((x)<(y)?(x):(y)) +#define MIN(x, y) ((x) < (y) ? (x) : (y)) #endif #ifndef MAX -#define MAX(x,y) ((x)>(y)?(x):(y)) +#define MAX(x, y) ((x) > (y) ? (x) : (y)) #endif -#define IS_POW2_OR_ZERO(x) (((x)&((x)-1)) == 0) +#define IS_POW2_OR_ZERO(x) (((x) & ((x) -1)) == 0) diff --git a/include/os_memory.h b/include/os_memory.h index 85cf35f0b..145586de4 100644 --- a/include/os_memory.h +++ b/include/os_memory.h @@ -4,10 +4,11 @@ #include "decorators.h" typedef struct meminfo_s { - unsigned int free_nvram_size; - unsigned int appMemory; - unsigned int systemSize; - unsigned int slots; + unsigned int free_nvram_size; + unsigned int appMemory; + unsigned int systemSize; + unsigned int slots; } meminfo_t; -SYSCALL PERMISSION(APPLICATION_FLAG_BOLOS_UX) void os_get_memory_info(meminfo_t* meminfo PLENGTH(sizeof(meminfo_t))); +SYSCALL PERMISSION(APPLICATION_FLAG_BOLOS_UX) void os_get_memory_info( + meminfo_t *meminfo PLENGTH(sizeof(meminfo_t))); diff --git a/include/os_nvm.h b/include/os_nvm.h index 2e328f40e..3f1811bda 100644 --- a/include/os_nvm.h +++ b/include/os_nvm.h @@ -6,11 +6,15 @@ #define NVM_ERASED_WORD_VALUE 0xFFFFFFFF -// write in persistent memory, to make things easy keep a layout of the memory in a structure and update fields upon needs -// The function throws exception when the requesting application buffer being written in its declared data segment. The later is declared during the application slot allocation (using --dataSize parameter in the python scripts) -// NOTE: accept copy from far memory to another far memory. +// write in persistent memory, to make things easy keep a layout of the memory in a structure and +// update fields upon needs The function throws exception when the requesting application buffer +// being written in its declared data segment. The later is declared during the application slot +// allocation (using --dataSize parameter in the python scripts) NOTE: accept copy from far memory +// to another far memory. // @param src_adr NULL to fill with 00's -SYSCALL void nvm_write(void *dst_adr PLENGTH(src_len), void *src_adr PLENGTH(src_len), unsigned int src_len); +SYSCALL void nvm_write(void *dst_adr PLENGTH(src_len), + void *src_adr PLENGTH(src_len), + unsigned int src_len); SYSCALL void nvm_erase(void *dst_adr PLENGTH(len), unsigned int len); @@ -22,12 +26,12 @@ SUDOCALL void nvm_write_page(unsigned int page_adr, bool force); SUDOCALL void nvm_erase_page(unsigned int page_adr); // any application can wipe the global pin, global seed, user's keys -// disabled for security reasons // SYSCALL void os_perso_wipe(void); -// erase seed, settings AND applications -SYSCALL void os_perso_erase_all(void); +// disabled for security reasons // SYSCALL void +// os_perso_wipe(void); erase seed, settings AND applications +SYSCALL void os_perso_erase_all(void); #ifndef BOLOS_OS_UPGRADER_APP // Wipe all data from N_application_registry.applications, // except language packs / background img void erase_all_except_user_config_apps(void); -#endif //(defined(HAVE_LANGUAGE_PACK) && !defined(BOLOS_OS_UPGRADER_APP)) +#endif //(defined(HAVE_LANGUAGE_PACK) && !defined(BOLOS_OS_UPGRADER_APP)) diff --git a/include/os_pic.h b/include/os_pic.h index f49a9b860..9445fce23 100644 --- a/include/os_pic.h +++ b/include/os_pic.h @@ -1,13 +1,13 @@ #pragma once // Position-independent code reference -// Function that align the dereferenced value in a rom struct to use it depending on the execution address. -// Can be used even if code is executing at the same place where it had been linked. +// Function that align the dereferenced value in a rom struct to use it depending on the execution +// address. Can be used even if code is executing at the same place where it had been linked. #if defined(HAVE_BOLOS) && !defined(BOLOS_OS_UPGRADER_APP) #define PIC(x) (x) #endif #ifndef PIC -#define PIC(x) pic((void *)x) +#define PIC(x) pic((void *) x) void *pic(void *linked_address); void *pic_internal(void *link_address); #endif diff --git a/include/os_pin.h b/include/os_pin.h index 067823101..c1bc42a00 100644 --- a/include/os_pin.h +++ b/include/os_pin.h @@ -13,21 +13,30 @@ #define DEFAULT_PIN_RETRIES 3 /* set_pin can update the pin if the perso is onboarded (tearing leads to perso wipe though) */ -SYSCALL PERMISSION(APPLICATION_FLAG_BOLOS_UX) void os_perso_set_pin(unsigned int identity, const unsigned char* pin PLENGTH(length), unsigned int length, bool update_crc); +SYSCALL PERMISSION(APPLICATION_FLAG_BOLOS_UX) void os_perso_set_pin(unsigned int identity, + const unsigned char *pin + PLENGTH(length), + unsigned int length, + bool update_crc); // set the currently unlocked identity pin. (change pin feature) - SYSCALL PERMISSION(APPLICATION_FLAG_BOLOS_UX) void os_perso_set_current_identity_pin(unsigned char* pin PLENGTH(length), unsigned int length); +SYSCALL PERMISSION(APPLICATION_FLAG_BOLOS_UX) void os_perso_set_current_identity_pin( + unsigned char *pin PLENGTH(length), + unsigned int length); /* * @return BOLOS_UX_OK if pin validated */ -SYSCALL bolos_bool_t os_global_pin_is_validated(void); +SYSCALL bolos_bool_t os_global_pin_is_validated(void); /** * Validating the pin also setup the identity linked with this pin (normal or alternate) * @return BOLOS_UX_OK if pin validated */ -SYSCALL PERMISSION(APPLICATION_FLAG_GLOBAL_PIN) bolos_bool_t os_global_pin_check(unsigned char* pin_buffer PLENGTH(pin_length), unsigned char pin_length); - SYSCALL PERMISSION(APPLICATION_FLAG_GLOBAL_PIN) void os_global_pin_invalidate(void); -SYSCALL PERMISSION(APPLICATION_FLAG_GLOBAL_PIN) unsigned int os_global_pin_retries(void); +SYSCALL PERMISSION(APPLICATION_FLAG_GLOBAL_PIN) +bolos_bool_t os_global_pin_check(unsigned char *pin_buffer PLENGTH(pin_length), + unsigned char pin_length); +SYSCALL PERMISSION(APPLICATION_FLAG_GLOBAL_PIN) void os_global_pin_invalidate(void); +SYSCALL PERMISSION(APPLICATION_FLAG_GLOBAL_PIN) +unsigned int os_global_pin_retries(void); /** * This function checks whether a PIN is present @@ -35,8 +44,7 @@ SYSCALL PERMISSION(APPLICATION_FLAG_GLOBAL_PIN) unsigned int os_global_pin_retri * is correct and if a PIN value has been written */ SYSCALL -bolos_bool_t os_perso_is_pin_set(void); - +bolos_bool_t os_perso_is_pin_set(void); #if defined(HAVE_AEM_PIN) /* ----------------------------------------------------------------------- */ @@ -52,22 +60,22 @@ bolos_bool_t os_perso_is_pin_set(void); /** * The minimum length of an AEM PIN, in bytes. */ -#define AEM_MIN_PIN_LENGTH 0x04 +#define AEM_MIN_PIN_LENGTH 0x04 /** * The maximum length of a AEM PIN associated response, in bytes, including * the trailing end-of-string character (which is automatically added by * the OS at the end of an APDU buffer). */ -#define AEM_RESPONSE_MAX_LENGTH 0x80 +#define AEM_RESPONSE_MAX_LENGTH 0x80 /** * The different supported formats for the AEM response, and the value of the * last one. */ -#define AEM_RESPONSE_FORMAT_TEXT 0x01 -#define AEM_RESPONSE_FORMAT_BMP_14x14 0x02 -#define AEM_RESPONSE_FORMAT_LAST AEM_RESPONSE_FORMAT_BMP_14x14 +#define AEM_RESPONSE_FORMAT_TEXT 0x01 +#define AEM_RESPONSE_FORMAT_BMP_14x14 0x02 +#define AEM_RESPONSE_FORMAT_LAST AEM_RESPONSE_FORMAT_BMP_14x14 /** * This function allows one to set a value to the AEM PIN, and activate the @@ -84,9 +92,9 @@ bolos_bool_t os_perso_is_pin_set(void); * @throw SWO_SEC_PIN_0D when either the device is not onboarded or the * user PIN has not been checked beforehand. */ -SYSCALL PERMISSION(APPLICATION_FLAG_BOLOS_UX) -void os_aem_set_pin(unsigned char* aem_pin PLENGTH(aem_pin_length), - unsigned int aem_pin_length); +SYSCALL PERMISSION(APPLICATION_FLAG_BOLOS_UX) void os_aem_set_pin(unsigned char *aem_pin + PLENGTH(aem_pin_length), + unsigned int aem_pin_length); /** * This function allows one to unset the AEM PIN value (in such a case, it @@ -96,8 +104,7 @@ void os_aem_set_pin(unsigned char* aem_pin PLENGTH(aem_pin_length), * @throw SWO_SEC_PIN_0E, when either the device is not onboarded or the * user PIN has not been checked beforehand. */ -SYSCALL PERMISSION(APPLICATION_FLAG_BOLOS_UX) -void os_aem_unset_pin(void); +SYSCALL PERMISSION(APPLICATION_FLAG_BOLOS_UX) void os_aem_unset_pin(void); /** * This function allows one to know whether the AEM PIN has been set. @@ -106,7 +113,7 @@ void os_aem_unset_pin(void); * @return BOLOS_TRUE if the AEM PIN has been set, any other value otherwise * (depending on the failed internal check). */ -SYSCALL PERMISSION(APPLICATION_FLAG_BOLOS_UX) +SYSCALL PERMISSION(APPLICATION_FLAG_BOLOS_UX) bolos_bool_t os_aem_is_pin_set(void); /** @@ -126,11 +133,10 @@ bolos_bool_t os_aem_is_pin_set(void); * @throw SWO_SEC_PIN_0F, when either the device is not onboarded or the * user PIN has not been checked beforehand. */ -SYSCALL PERMISSION(APPLICATION_FLAG_BOLOS_UX) -void os_aem_set_response( - unsigned char* aem_response PLENGTH(aem_response_length), - unsigned int aem_response_length, - unsigned char aem_response_format); +SYSCALL PERMISSION(APPLICATION_FLAG_BOLOS_UX) void os_aem_set_response( + unsigned char *aem_response PLENGTH(aem_response_length), + unsigned int aem_response_length, + unsigned char aem_response_format); /** * This function allows one to activate the AEM response. @@ -141,8 +147,7 @@ void os_aem_set_response( * user PIN has not been checked beforehand or the length of the response is * zero. */ -SYSCALL PERMISSION(APPLICATION_FLAG_BOLOS_UX) -void os_aem_activate_response(void); +SYSCALL PERMISSION(APPLICATION_FLAG_BOLOS_UX) void os_aem_activate_response(void); /** * This function allows one to deactivate the AEM response, and @@ -152,8 +157,7 @@ void os_aem_activate_response(void); * @throw SWO_SEC_PIN_11, when either the device is not onboarded or the * user PIN has not been checked beforehand. */ -SYSCALL PERMISSION(APPLICATION_FLAG_BOLOS_UX) -void os_aem_deactivate_response(void); +SYSCALL PERMISSION(APPLICATION_FLAG_BOLOS_UX) void os_aem_deactivate_response(void); /** * This function allows one to know whether the AEM response @@ -163,7 +167,7 @@ void os_aem_deactivate_response(void); * @return BOLOS_TRUE if the response has been set and activated, any other * value otherwise (depending on the failed internal check). */ -SYSCALL PERMISSION(APPLICATION_FLAG_BOLOS_UX) +SYSCALL PERMISSION(APPLICATION_FLAG_BOLOS_UX) bolos_bool_t os_aem_is_response_active(void); /** @@ -174,7 +178,7 @@ bolos_bool_t os_aem_is_response_active(void); * @return BOLOS_TRUE if the feature is active, any other value otherwise * (depending on the failed internal check). */ -SYSCALL PERMISSION(APPLICATION_FLAG_BOLOS_UX) +SYSCALL PERMISSION(APPLICATION_FLAG_BOLOS_UX) bolos_bool_t os_aem_is_feature_active(void); /** @@ -183,14 +187,14 @@ bolos_bool_t os_aem_is_feature_active(void); * 'os_aem_get_response' function. * @return The length of the currently stored response. */ -SYSCALL PERMISSION(APPLICATION_FLAG_BOLOS_UX) +SYSCALL PERMISSION(APPLICATION_FLAG_BOLOS_UX) unsigned char os_aem_get_response_length(void); /** * This function allows one to retrieve the format of the response. * @return The format of the currently stored response. */ -SYSCALL PERMISSION(APPLICATION_FLAG_BOLOS_UX) +SYSCALL PERMISSION(APPLICATION_FLAG_BOLOS_UX) unsigned char os_aem_get_response_format(void); /** @@ -207,10 +211,9 @@ unsigned char os_aem_get_response_format(void); * @throw SWO_PAR_LEN_15 if the required length is greater than the response * length. */ -SYSCALL PERMISSION(APPLICATION_FLAG_BOLOS_UX) -void os_aem_get_response(char* output_response_buffer - PLENGTH(input_required_length), - unsigned char input_required_length); +SYSCALL PERMISSION(APPLICATION_FLAG_BOLOS_UX) void os_aem_get_response( + char *output_response_buffer PLENGTH(input_required_length), + unsigned char input_required_length); /** * This function allows one to check a presented PIN against the internally @@ -228,17 +231,15 @@ void os_aem_get_response(char* output_response_buffer * @throw SWO_SEC_CHK_18 when the PIN verification detects an error in * the processing. */ -SYSCALL PERMISSION(APPLICATION_FLAG_GLOBAL_PIN) -bolos_bool_t os_aem_check_pin( - unsigned char* aem_pin_buffer PLENGTH(aem_pin_length), - unsigned char aem_pin_length); +SYSCALL PERMISSION(APPLICATION_FLAG_GLOBAL_PIN) +bolos_bool_t os_aem_check_pin(unsigned char *aem_pin_buffer PLENGTH(aem_pin_length), + unsigned char aem_pin_length); /** * This function allows one to invalidate the AEM PIN, regardless of its * validation state. */ -SYSCALL PERMISSION(APPLICATION_FLAG_GLOBAL_PIN) -void os_aem_invalidate_pin(void); +SYSCALL PERMISSION(APPLICATION_FLAG_GLOBAL_PIN) void os_aem_invalidate_pin(void); /** * This function allows one to retrieve the remaining attempts at verifying @@ -249,7 +250,7 @@ void os_aem_invalidate_pin(void); * @throw SWO_SEC_PIN_12 when eiher the device is not onboarded or the * AEM PIN is not set. */ -SYSCALL PERMISSION(APPLICATION_FLAG_GLOBAL_PIN) +SYSCALL PERMISSION(APPLICATION_FLAG_GLOBAL_PIN) unsigned int os_aem_get_ptc(void); /** @@ -261,4 +262,4 @@ unsigned int os_aem_get_ptc(void); SYSCALL bolos_bool_t os_aem_is_pin_validated(void); -#endif // HAVE_AEM_PIN +#endif // HAVE_AEM_PIN diff --git a/include/os_registry.h b/include/os_registry.h index d6830ec07..331c12ed4 100644 --- a/include/os_registry.h +++ b/include/os_registry.h @@ -7,37 +7,61 @@ /* ----------------------------------------------------------------------- */ /* - REGISTRY-RELATED - */ /* ----------------------------------------------------------------------- */ -// read from the application's install parameter TLV (if present), else 0 is returned (no exception thrown). -// takes into account the currently loaded application +// read from the application's install parameter TLV (if present), else 0 is returned (no exception +// thrown). takes into account the currently loaded application #define OS_REGISTRY_GET_TAG_OFFSET_COMPARE_WITH_BUFFER (0x80000000UL) -#define OS_REGISTRY_GET_TAG_OFFSET_GET_LENGTH (0x40000000UL) +#define OS_REGISTRY_GET_TAG_OFFSET_GET_LENGTH (0x40000000UL) /** - * @param appidx The application entry index in the registry (raw, not filtering ux or whatever). If the entry index correspond to the application being installed then RAM structure content is used instead of the NVRAM registry. - * @param tlvoffset The offset within the install parameters memory area, in bytes. Useful if tag is present multiple times. Can be null. The tlv offset is the offset of the tag in the install parameters area when a tag is matched. This way long tag can be read in multiple time without the need to play with the tlvoffset. Add +1 to skip to the next one when searching for multiple tag occurrences. + * @param appidx The application entry index in the registry (raw, not filtering ux or whatever). If + * the entry index correspond to the application being installed then RAM structure content is used + * instead of the NVRAM registry. + * @param tlvoffset The offset within the install parameters memory area, in bytes. Useful if tag is + * present multiple times. Can be null. The tlv offset is the offset of the tag in the install + * parameters area when a tag is matched. This way long tag can be read in multiple time without the + * need to play with the tlvoffset. Add +1 to skip to the next one when searching for multiple tag + * occurrences. * @param tag The tag to be searched for - * @param value_offset The offset within the value for this occurrence of the tag. The OS_REGISTRY_GET_TAG_OFFSET_COMPARE_WITH_BUFFER or OS_REGISTRY_GET_TAG_OFFSET_GET_LENGTH can be ORed to perform meta operation on the TLV occurrence. - * @param buffer The user buffer for comparison or to retrieve the value of the tag at the given offset. - * @param maxlength Size of the buffer to be compared OR to be retrieved (trimmed depending the TLV effective length). + * @param value_offset The offset within the value for this occurrence of the tag. The + * OS_REGISTRY_GET_TAG_OFFSET_COMPARE_WITH_BUFFER or OS_REGISTRY_GET_TAG_OFFSET_GET_LENGTH can be + * ORed to perform meta operation on the TLV occurrence. + * @param buffer The user buffer for comparison or to retrieve the value of the tag at the given + * offset. + * @param maxlength Size of the buffer to be compared OR to be retrieved (trimmed depending the TLV + * effective length). */ -SYSCALL PERMISSION(APPLICATION_FLAG_BOLOS_UX) unsigned int os_registry_get_tag(unsigned int app_idx, unsigned int* tlvoffset, unsigned int tag, unsigned int value_offset, void* buffer PLENGTH(maxlength), unsigned int maxlength); +SYSCALL PERMISSION(APPLICATION_FLAG_BOLOS_UX) +unsigned int os_registry_get_tag(unsigned int app_idx, + unsigned int *tlvoffset, + unsigned int tag, + unsigned int value_offset, + void *buffer PLENGTH(maxlength), + unsigned int maxlength); // Copy the currently running application tag from its install parameters to the given user buffer. -// Only APPNAME/APPVERSION/DERIVEPATH/ICON tags are retrievable to avoid install parameters private information. -// Warning: this function returns tag content of the application lastly scheduled to run, not the tag content of the currently executed piece of code (libraries subcalls) - SYSCALL unsigned int os_registry_get_current_app_tag(unsigned int tag, unsigned char* buffer PLENGTH(maxlen), unsigned int maxlen); +// Only APPNAME/APPVERSION/DERIVEPATH/ICON tags are retrievable to avoid install parameters private +// information. Warning: this function returns tag content of the application lastly scheduled to +// run, not the tag content of the currently executed piece of code (libraries subcalls) +SYSCALL unsigned int os_registry_get_current_app_tag(unsigned int tag, + unsigned char *buffer PLENGTH(maxlen), + unsigned int maxlen); /** - * This function deletes the application mentioned with its index, as well as all the applications depending on it. + * This function deletes the application mentioned with its index, as well as all the applications + * depending on it. * @param index The index of the the application to suppress. */ - SYSCALL PERMISSION(APPLICATION_FLAG_BOLOS_UX) void os_registry_delete_app_and_dependees(unsigned int app_idx); +SYSCALL PERMISSION(APPLICATION_FLAG_BOLOS_UX) void os_registry_delete_app_and_dependees( + unsigned int app_idx); /** * This function deletes all the installed applications. */ SYSCALL PERMISSION(APPLICATION_FLAG_BOLOS_UX) void os_registry_delete_all_apps(void); -SYSCALL PERMISSION(APPLICATION_FLAG_BOLOS_UX) unsigned int os_registry_count(void); +SYSCALL PERMISSION(APPLICATION_FLAG_BOLOS_UX) +unsigned int os_registry_count(void); // return any entry, activated or not, enabled or not, empty or not. to enable full control -SYSCALL PERMISSION(APPLICATION_FLAG_BOLOS_UX) void os_registry_get(unsigned int app_idx, application_t* out_application_entry PLENGTH(sizeof(application_t))); +SYSCALL PERMISSION(APPLICATION_FLAG_BOLOS_UX) void os_registry_get( + unsigned int app_idx, + application_t *out_application_entry PLENGTH(sizeof(application_t))); diff --git a/include/os_screen.h b/include/os_screen.h index 95cab196b..ce0be05ff 100644 --- a/include/os_screen.h +++ b/include/os_screen.h @@ -5,7 +5,7 @@ #ifdef HAVE_BAGL #ifdef HAVE_SE_SCREEN -//SYSCALL void screen_write_frame(unsigned char* framebuffer PLENGTH(BAGL_WIDTH*BAGL_HEIGHT/8)); +// SYSCALL void screen_write_frame(unsigned char* framebuffer PLENGTH(BAGL_WIDTH*BAGL_HEIGHT/8)); /** * Initialize the screen driver and blank the screen. */ @@ -26,14 +26,31 @@ SYSCALL PERMISSION(APPLICATION_FLAG_BOLOS_UX) void screen_set_brightness(unsigne /** * Require a specific zone not to be cleared/drawn by any graphic HAL to implement screen overlay */ -SYSCALL void screen_set_keepout(unsigned int x, unsigned int y, unsigned int width, unsigned int height); +SYSCALL void screen_set_keepout(unsigned int x, + unsigned int y, + unsigned int width, + unsigned int height); /** - * Draw the given bitmap, with the given colors and position into the screen buffer. Don't update the screen driver. + * Draw the given bitmap, with the given colors and position into the screen buffer. Don't update + * the screen driver. */ -SYSCALL void bagl_hal_draw_bitmap_within_rect(int x, int y, unsigned int width, unsigned int height, unsigned int color_count, const unsigned int *colors PLENGTH(color_count*4), unsigned int bit_per_pixel, const unsigned char* bitmap PLENGTH(1+bitmap_length_bits/8), unsigned int bitmap_length_bits); +SYSCALL void bagl_hal_draw_bitmap_within_rect(int x, + int y, + unsigned int width, + unsigned int height, + unsigned int color_count, + const unsigned int *colors PLENGTH(color_count * 4), + unsigned int bit_per_pixel, + const unsigned char *bitmap + PLENGTH(1 + bitmap_length_bits / 8), + unsigned int bitmap_length_bits); /** * Fill a rectangle with a given color in the screen buffer, but don't update the screen driver. */ -SYSCALL void bagl_hal_draw_rect(unsigned int color, int x, int y, unsigned int width, unsigned int height); -#endif // HAVE_SE_SCREEN -#endif // HAVE_BAGL +SYSCALL void bagl_hal_draw_rect(unsigned int color, + int x, + int y, + unsigned int width, + unsigned int height); +#endif // HAVE_SE_SCREEN +#endif // HAVE_BAGL diff --git a/include/os_seed.h b/include/os_seed.h index da6ead901..4941b71e3 100644 --- a/include/os_seed.h +++ b/include/os_seed.h @@ -11,28 +11,28 @@ /* - SEED FEATURE - */ /* ----------------------------------------------------------------------- */ -#define BOLOS_UX_ONBOARDING_ALGORITHM_BIP39 1 -#define BOLOS_UX_ONBOARDING_ALGORITHM_ELECTRUM 2 +#define BOLOS_UX_ONBOARDING_ALGORITHM_BIP39 1 +#define BOLOS_UX_ONBOARDING_ALGORITHM_ELECTRUM 2 #if defined(HAVE_VAULT_RECOVERY_ALGO) -#define BOLOS_UX_ONBOARDING_ALGORITHM_BIP39_VAULT_REC_MSK 3 -#define BOLOS_VAULT_RECOVERY_WORK_BUFFER_SIZE 64 -#endif // HAVE_VAULT_RECOVERY_ALGO -#define BOLOS_MASTER_SEED_LEN (32) +#define BOLOS_UX_ONBOARDING_ALGORITHM_BIP39_VAULT_REC_MSK 3 +#define BOLOS_VAULT_RECOVERY_WORK_BUFFER_SIZE 64 +#endif // HAVE_VAULT_RECOVERY_ALGO +#define BOLOS_MASTER_SEED_LEN (32) typedef enum { - SET_SEED = 0, - SET_STATE, - GET_STATE + SET_SEED = 0, + SET_STATE, + GET_STATE } os_action_t; /** * Set the persisted seed if none yet, else override the volatile seed (in RAM) */ -SYSCALL PERMISSION(APPLICATION_FLAG_BOLOS_UX) void os_perso_set_seed( - unsigned int identity, - unsigned int algorithm, - unsigned char *seed PLENGTH(length), - unsigned int length); +SYSCALL PERMISSION(APPLICATION_FLAG_BOLOS_UX) void os_perso_set_seed(unsigned int identity, + unsigned int algorithm, + unsigned char *seed + PLENGTH(length), + unsigned int length); SYSCALL PERMISSION(APPLICATION_FLAG_BOLOS_UX) void os_perso_derive_and_set_seed( unsigned char identity, @@ -45,27 +45,27 @@ SYSCALL PERMISSION(APPLICATION_FLAG_BOLOS_UX) void os_perso_derive_and_set_seed( #if defined(HAVE_VAULT_RECOVERY_ALGO) SYSCALL PERMISSION(APPLICATION_FLAG_BOLOS_UX) void os_perso_derive_and_prepare_seed( - const char * words, + const char *words, unsigned int words_length, - uint8_t *vault_recovery_work_buffer); + uint8_t *vault_recovery_work_buffer); SYSCALL PERMISSION(APPLICATION_FLAG_BOLOS_UX) void os_perso_derive_and_xor_seed( uint8_t *vault_recovery_work_buffer); -SYSCALL PERMISSION(APPLICATION_FLAG_BOLOS_UX) unsigned char os_perso_get_seed_algorithm(void); -#endif // HAVE_VAULT_RECOVERY_ALGO +SYSCALL PERMISSION(APPLICATION_FLAG_BOLOS_UX) +unsigned char os_perso_get_seed_algorithm(void); +#endif // HAVE_VAULT_RECOVERY_ALGO -SYSCALL PERMISSION(APPLICATION_FLAG_BOLOS_UX) void os_perso_set_words( - const unsigned char *words PLENGTH(length), - unsigned int length); +SYSCALL PERMISSION(APPLICATION_FLAG_BOLOS_UX) void os_perso_set_words(const unsigned char *words + PLENGTH(length), + unsigned int length); SYSCALL PERMISSION(APPLICATION_FLAG_BOLOS_UX) void os_perso_finalize(void); #if defined(HAVE_RECOVER) -SYSCALL PERMISSION(APPLICATION_FLAG_BOLOS_UX) void os_perso_master_seed( - uint8_t *master_seed PLENGTH(length), - size_t length, - os_action_t action); -SYSCALL PERMISSION(APPLICATION_FLAG_BOLOS_UX) void os_perso_recover_state( - uint8_t *state, - os_action_t action); -#endif // HAVE_RECOVER +SYSCALL PERMISSION(APPLICATION_FLAG_BOLOS_UX) void os_perso_master_seed(uint8_t *master_seed + PLENGTH(length), + size_t length, + os_action_t action); +SYSCALL PERMISSION(APPLICATION_FLAG_BOLOS_UX) void os_perso_recover_state(uint8_t *state, + os_action_t action); +#endif // HAVE_RECOVER // checked in the ux flow to avoid asking the pin for example // NBA : could also be checked by applications running in insecure mode - thus unprivilegied @@ -73,22 +73,22 @@ SYSCALL PERMISSION(APPLICATION_FLAG_BOLOS_UX) void os_perso_recover_state( SYSCALL bolos_bool_t os_perso_isonboarded(void); enum { - ONBOARDING_STATUS_WELCOME = 0, - ONBOARDING_STATUS_WELCOME_STEP2, - ONBOARDING_STATUS_WELCOME_STEP5, - ONBOARDING_STATUS_WELCOME_STEP6, - ONBOARDING_STATUS_WELCOME_REMEMBER, - ONBOARDING_STATUS_SETUP_CHOICE, - ONBOARDING_STATUS_PIN, - ONBOARDING_STATUS_NEW_DEVICE, - ONBOARDING_STATUS_NEW_DEVICE_CONFIRMING, - ONBOARDING_STATUS_RESTORE_SEED, - ONBOARDING_STATUS_SAFETY_WARNINGS, - ONBOARDING_STATUS_READY, - ONBOARDING_STATUS_CHOOSE_NAME, - ONBOARDING_STATUS_RECOVER_RESTORE_SEED, - ONBOARDING_STATUS_SETUP_CHOICE_RESTORE_SEED, - ONBOARDING_STATUS_CHECKING + ONBOARDING_STATUS_WELCOME = 0, + ONBOARDING_STATUS_WELCOME_STEP2, + ONBOARDING_STATUS_WELCOME_STEP5, + ONBOARDING_STATUS_WELCOME_STEP6, + ONBOARDING_STATUS_WELCOME_REMEMBER, + ONBOARDING_STATUS_SETUP_CHOICE, + ONBOARDING_STATUS_PIN, + ONBOARDING_STATUS_NEW_DEVICE, + ONBOARDING_STATUS_NEW_DEVICE_CONFIRMING, + ONBOARDING_STATUS_RESTORE_SEED, + ONBOARDING_STATUS_SAFETY_WARNINGS, + ONBOARDING_STATUS_READY, + ONBOARDING_STATUS_CHOOSE_NAME, + ONBOARDING_STATUS_RECOVER_RESTORE_SEED, + ONBOARDING_STATUS_SETUP_CHOICE_RESTORE_SEED, + ONBOARDING_STATUS_CHECKING }; SYSCALL void os_perso_set_onboarding_status(unsigned int state, unsigned int count, @@ -99,32 +99,34 @@ SYSCALL void os_perso_set_onboarding_status(unsigned int state, #ifndef HAVE_BOLOS DEPRECATED #endif -SYSCALL void os_perso_derive_node_bip32(cx_curve_t curve, - const unsigned int *path PLENGTH(4 * (pathLength & 0x0FFFFFFFu)), - unsigned int pathLength, +SYSCALL void os_perso_derive_node_bip32(cx_curve_t curve, + const unsigned int *path + PLENGTH(4 * (pathLength & 0x0FFFFFFFu)), + unsigned int pathLength, unsigned char *privateKey PLENGTH(64), unsigned char *chain PLENGTH(32)); -#define HDW_NORMAL 0 +#define HDW_NORMAL 0 #define HDW_ED25519_SLIP10 1 // symmetric key derivation according to SLIP-0021 // this only supports derivation of the master node (level 1) -// the beginning of the authorized path is to be provided in the authorized derivation tag of the registry -// starting with a \x00 -// Note: for SLIP21, the path is a string and the pathLength is the number of chars including the starting \0 byte. -// However, firewall checks are processing a number of integers, therefore, take care not to locate the buffer too far -// in memory to pass the firewall check. -#define HDW_SLIP21 2 +// the beginning of the authorized path is to be provided in the authorized derivation tag of the +// registry starting with a \x00 Note: for SLIP21, the path is a string and the pathLength is the +// number of chars including the starting \0 byte. However, firewall checks are processing a number +// of integers, therefore, take care not to locate the buffer too far in memory to pass the firewall +// check. +#define HDW_SLIP21 2 -// derive the seed for the requested BIP32 path, with the custom provided seed_key for the sha512 hmac ("Bitcoin Seed", -// "Nist256p1 Seed", "ed25519 seed", ...) -// Deprecated : see "os_derive_bip32_with_seed_no_throw" +// derive the seed for the requested BIP32 path, with the custom provided seed_key for the sha512 +// hmac ("Bitcoin Seed", "Nist256p1 Seed", "ed25519 seed", ...) Deprecated : see +// "os_derive_bip32_with_seed_no_throw" #ifndef HAVE_BOLOS DEPRECATED #endif -SYSCALL void os_perso_derive_node_with_seed_key(unsigned int mode, - cx_curve_t curve, - const unsigned int *path PLENGTH(4 * (pathLength & 0x0FFFFFFFu)), +SYSCALL void os_perso_derive_node_with_seed_key(unsigned int mode, + cx_curve_t curve, + const unsigned int *path + PLENGTH(4 * (pathLength & 0x0FFFFFFFu)), unsigned int pathLength, unsigned char *privateKey PLENGTH(64), unsigned char *chain PLENGTH(32), @@ -162,36 +164,33 @@ WARN_UNUSED_RESULT static inline cx_err_t os_derive_bip32_with_seed_no_throw( const unsigned int *path, unsigned int path_len, unsigned char raw_privkey[static 64], - unsigned char * chain_code, - unsigned char * seed, - unsigned int seed_len) { + unsigned char *chain_code, + unsigned char *seed, + unsigned int seed_len) +{ cx_err_t error = CX_OK; - BEGIN_TRY { - TRY { - // ignore the deprecated warning, pragma to remove when the "no throw" OS function will be available - #pragma GCC diagnostic push - #pragma GCC diagnostic ignored "-Wdeprecated-declarations" + BEGIN_TRY + { + TRY + { +// ignore the deprecated warning, pragma to remove when the "no throw" OS function will be available +#pragma GCC diagnostic push +#pragma GCC diagnostic ignored "-Wdeprecated-declarations" // Derive the seed with path - os_perso_derive_node_bip32_seed_key(derivation_mode, - curve, - path, - path_len, - raw_privkey, - chain_code, - seed, - seed_len); - #pragma GCC diagnostic pop + os_perso_derive_node_bip32_seed_key( + derivation_mode, curve, path, path_len, raw_privkey, chain_code, seed, seed_len); +#pragma GCC diagnostic pop } - CATCH_OTHER(e) { + CATCH_OTHER(e) + { error = e; // Make sure the caller doesn't use uninitialized data in case // the return code is not checked. explicit_bzero(raw_privkey, 64); } - FINALLY { - } + FINALLY {} } END_TRY; @@ -216,30 +215,25 @@ WARN_UNUSED_RESULT static inline cx_err_t os_derive_bip32_with_seed_no_throw( * - CX_INTERNAL_ERROR */ WARN_UNUSED_RESULT static inline cx_err_t os_derive_bip32_no_throw( - cx_curve_t curve, - const unsigned int *path, - unsigned int path_len, - unsigned char raw_privkey[static 64], - unsigned char *chain_code) { - return os_derive_bip32_with_seed_no_throw(HDW_NORMAL, - curve, - path, - path_len, - raw_privkey, - chain_code, - NULL, - 0); + cx_curve_t curve, + const unsigned int *path, + unsigned int path_len, + unsigned char raw_privkey[static 64], + unsigned char *chain_code) +{ + return os_derive_bip32_with_seed_no_throw( + HDW_NORMAL, curve, path, path_len, raw_privkey, chain_code, NULL, 0); } // Deprecated : see "os_derive_eip2333_no_throw" #ifndef HAVE_BOLOS DEPRECATED #endif -SYSCALL void os_perso_derive_eip2333( - cx_curve_t curve, - const unsigned int *path PLENGTH(4 * (pathLength & 0x0FFFFFFFu)), - unsigned int pathLength, - unsigned char *privateKey PLENGTH(32)); +SYSCALL void os_perso_derive_eip2333(cx_curve_t curve, + const unsigned int *path PLENGTH(4 + * (pathLength & 0x0FFFFFFFu)), + unsigned int pathLength, + unsigned char *privateKey PLENGTH(32)); /** * @brief Gets the private key from the device seed using the specified eip2333 path. @@ -257,30 +251,33 @@ SYSCALL void os_perso_derive_eip2333( * - CX_INTERNAL_ERROR */ WARN_UNUSED_RESULT static inline cx_err_t os_derive_eip2333_no_throw( - cx_curve_t curve, - const unsigned int *path, - unsigned int path_len, - unsigned char raw_privkey[static 64]) { + cx_curve_t curve, + const unsigned int *path, + unsigned int path_len, + unsigned char raw_privkey[static 64]) +{ cx_err_t error = CX_OK; - BEGIN_TRY { - TRY { - // ignore the deprecated warning, pragma to remove when the "no throw" OS function will be available - #pragma GCC diagnostic push - #pragma GCC diagnostic ignored "-Wdeprecated-declarations" + BEGIN_TRY + { + TRY + { +// ignore the deprecated warning, pragma to remove when the "no throw" OS function will be available +#pragma GCC diagnostic push +#pragma GCC diagnostic ignored "-Wdeprecated-declarations" // Derive the seed with path os_perso_derive_eip2333(curve, path, path_len, raw_privkey); - #pragma GCC diagnostic pop +#pragma GCC diagnostic pop } - CATCH_OTHER(e) { + CATCH_OTHER(e) + { error = e; // Make sure the caller doesn't use uninitialized data in case // the return code is not checked. explicit_bzero(raw_privkey, 64); } - FINALLY { - } + FINALLY {} } END_TRY; @@ -289,11 +286,12 @@ WARN_UNUSED_RESULT static inline cx_err_t os_derive_eip2333_no_throw( /** * Generate a seed based cookie - * seed => derivation (path 0xda7aba5e/0xc1a551c5) => priv key =SECP256K1=> pubkey => sha512 => cookie + * seed => derivation (path 0xda7aba5e/0xc1a551c5) => priv key =SECP256K1=> pubkey => sha512 => + * cookie */ #if defined(HAVE_SEED_COOKIE) // seed_cookie length has to be CX_SHA512_SIZE. // return BOLOS_TRUE if the seed has been generated, return BOLOS_FALSE otherwise. SYSCALL bolos_bool_t os_perso_seed_cookie(unsigned char *seed_cookie PLENGTH(CX_SHA512_SIZE)); -#endif // HAVE_SEED_COOKIE +#endif // HAVE_SEED_COOKIE diff --git a/include/os_settings.h b/include/os_settings.h index 14891b2ab..42ef5ed1a 100644 --- a/include/os_settings.h +++ b/include/os_settings.h @@ -7,100 +7,104 @@ /* - SETTINGS FUNCTIONS - */ /* ----------------------------------------------------------------------- */ -#define IS_NOTIF_ENABLED(setting) ((setting & 0b10)?false:true) -#define IS_TAP_ENABLED(setting) ((setting & 0b01)?false:true) -#define GET_SOUND_SETTING_VALUE(notif_setting, feedback_setting) ((uint32_t) ((!(feedback_setting& 0b01)) | ((!(notif_setting) << 1) & 0b10))) +#define IS_NOTIF_ENABLED(setting) ((setting & 0b10) ? false : true) +#define IS_TAP_ENABLED(setting) ((setting & 0b01) ? false : true) +#define GET_SOUND_SETTING_VALUE(notif_setting, feedback_setting) \ + ((uint32_t) ((!(feedback_setting & 0b01)) | ((!(notif_setting) << 1) & 0b10))) // Keep a V0 of the settings to make updates easier // Balenos_v2.0.2 typedef enum os_setting_v0_e { - OS_SETTING_BRIGHTNESS_V0, - OS_SETTING_INVERT_V0, - OS_SETTING_ROTATION_V0, - OS_SETTING_MCU_UPGRADE_V0=OS_SETTING_ROTATION_V0, + OS_SETTING_BRIGHTNESS_V0, + OS_SETTING_INVERT_V0, + OS_SETTING_ROTATION_V0, + OS_SETTING_MCU_UPGRADE_V0 = OS_SETTING_ROTATION_V0, #ifdef HAVE_BOLOS_NOT_SHUFFLED_PIN - OS_SETTING_NOSHUFFLE_PIN_V0, -#endif // HAVE_BOLOS_NOT_SHUFFLED_PIN - OS_SETTING_AUTO_LOCK_DELAY_V0, - OS_SETTING_SCREEN_LOCK_DELAY_V0, - OS_SETTING_POWER_OFF_DELAY_V0, + OS_SETTING_NOSHUFFLE_PIN_V0, +#endif // HAVE_BOLOS_NOT_SHUFFLED_PIN + OS_SETTING_AUTO_LOCK_DELAY_V0, + OS_SETTING_SCREEN_LOCK_DELAY_V0, + OS_SETTING_POWER_OFF_DELAY_V0, - OS_SETTING_PLANEMODE_V0, + OS_SETTING_PLANEMODE_V0, - // default off - OS_SETTING_PRIVACY_MODE_V0, + // default off + OS_SETTING_PRIVACY_MODE_V0, - // before that value, all settings are only making use of the length value with a null buffer to be set, and are returned through the return value with a maxlength = 0 in the get. - OS_SETTING_LAST_INT_V0, + // before that value, all settings are only making use of the length value with a null buffer to + // be set, and are returned through the return value with a maxlength = 0 in the get. + OS_SETTING_LAST_INT_V0, - // screen saver string to display - OS_SETTING_SAVER_STRING_V0=OS_SETTING_LAST_INT_V0, - OS_SETTING_DEVICENAME_V0, - OS_SETTING_BLEMACADR_V0, + // screen saver string to display + OS_SETTING_SAVER_STRING_V0 = OS_SETTING_LAST_INT_V0, + OS_SETTING_DEVICENAME_V0, + OS_SETTING_BLEMACADR_V0, - OS_SETTING_LAST_V0, + OS_SETTING_LAST_V0, } os_setting_v0_t; typedef enum os_setting_v1_e { - OS_SETTING_BRIGHTNESS_V1, - OS_SETTING_INVERT_V1, - OS_SETTING_ROTATION_V1, - OS_SETTING_MCU_UPGRADE_V1=OS_SETTING_ROTATION_V1, + OS_SETTING_BRIGHTNESS_V1, + OS_SETTING_INVERT_V1, + OS_SETTING_ROTATION_V1, + OS_SETTING_MCU_UPGRADE_V1 = OS_SETTING_ROTATION_V1, #ifdef HAVE_BOLOS_NOT_SHUFFLED_PIN - OS_SETTING_NOSHUFFLE_PIN_V1, -#endif // HAVE_BOLOS_NOT_SHUFFLED_PIN - OS_SETTING_AUTO_LOCK_DELAY_V1, - OS_SETTING_SCREEN_LOCK_DELAY_V1, - OS_SETTING_POWER_OFF_DELAY_V1, + OS_SETTING_NOSHUFFLE_PIN_V1, +#endif // HAVE_BOLOS_NOT_SHUFFLED_PIN + OS_SETTING_AUTO_LOCK_DELAY_V1, + OS_SETTING_SCREEN_LOCK_DELAY_V1, + OS_SETTING_POWER_OFF_DELAY_V1, - OS_SETTING_PLANEMODE_V1, + OS_SETTING_PLANEMODE_V1, - // default off - OS_SETTING_PRIVACY_MODE_V1, + // default off + OS_SETTING_PRIVACY_MODE_V1, - OS_SETTING_LANGUAGE_V1, + OS_SETTING_LANGUAGE_V1, - // before that value, all settings are only making use of the length value with a null buffer to be set, and are returned through the return value with a maxlength = 0 in the get. - OS_SETTING_LAST_INT_V1, + // before that value, all settings are only making use of the length value with a null buffer to + // be set, and are returned through the return value with a maxlength = 0 in the get. + OS_SETTING_LAST_INT_V1, - // screen saver string to display - OS_SETTING_SAVER_STRING_V1=OS_SETTING_LAST_INT_V1, - OS_SETTING_DEVICENAME_V1, - OS_SETTING_BLEMACADR_V1, + // screen saver string to display + OS_SETTING_SAVER_STRING_V1 = OS_SETTING_LAST_INT_V1, + OS_SETTING_DEVICENAME_V1, + OS_SETTING_BLEMACADR_V1, - OS_SETTING_LAST_V1, + OS_SETTING_LAST_V1, } os_setting_v1_t; typedef enum os_setting_e { - OS_SETTING_BRIGHTNESS, - OS_SETTING_INVERT, - OS_SETTING_ROTATION, - OS_SETTING_MCU_UPGRADE=OS_SETTING_ROTATION, - OS_SETTING_AUTO_LOCK_DELAY, - OS_SETTING_SCREEN_LOCK_DELAY, - OS_SETTING_POWER_OFF_DELAY, + OS_SETTING_BRIGHTNESS, + OS_SETTING_INVERT, + OS_SETTING_ROTATION, + OS_SETTING_MCU_UPGRADE = OS_SETTING_ROTATION, + OS_SETTING_AUTO_LOCK_DELAY, + OS_SETTING_SCREEN_LOCK_DELAY, + OS_SETTING_POWER_OFF_DELAY, - OS_SETTING_PLANEMODE, + OS_SETTING_PLANEMODE, - // default off - OS_SETTING_PRIVACY_MODE, + // default off + OS_SETTING_PRIVACY_MODE, - OS_SETTING_LANGUAGE, + OS_SETTING_LANGUAGE, - OS_SETTING_PIEZO_SOUND, + OS_SETTING_PIEZO_SOUND, - // before that value, all settings are only making use of the length value with a null buffer to be set, and are returned through the return value with a maxlength = 0 in the get. - OS_SETTING_LAST_INT, + // before that value, all settings are only making use of the length value with a null buffer to + // be set, and are returned through the return value with a maxlength = 0 in the get. + OS_SETTING_LAST_INT, - // screen saver string to display - OS_SETTING_SAVER_STRING=OS_SETTING_LAST_INT, - OS_SETTING_DEVICENAME, - OS_SETTING_BLEMACADR, + // screen saver string to display + OS_SETTING_SAVER_STRING = OS_SETTING_LAST_INT, + OS_SETTING_DEVICENAME, + OS_SETTING_BLEMACADR, - OS_SETTING_NFC_TAG_CONTENT, - OS_SETTING_FEATURES, + OS_SETTING_NFC_TAG_CONTENT, + OS_SETTING_FEATURES, - OS_SETTING_LAST, + OS_SETTING_LAST, } os_setting_t; /** @@ -108,21 +112,31 @@ typedef enum os_setting_e { * */ // if (os_settings[OS_SETTING_FEATURES] & OS_SETTING_FEATURES_NFC_ENABLED) then NFC is enabled -#define OS_SETTING_FEATURES_NFC_ENABLED 0x1 -// if (os_settings[OS_SETTING_FEATURES] & OS_SETTING_FEATURES_NO_PIN_SHUFFLE) then PIN shuffle is disable -#define OS_SETTING_FEATURES_NO_PIN_SHUFFLE 0x2 -// if (os_settings[OS_SETTING_FEATURES] & OS_SETTING_FEATURES_BATT_IN_SIDE) then Battery percentage in side screen is enabled -#define OS_SETTING_FEATURES_BATT_IN_SIDE 0x4 +#define OS_SETTING_FEATURES_NFC_ENABLED 0x1 +// if (os_settings[OS_SETTING_FEATURES] & OS_SETTING_FEATURES_NO_PIN_SHUFFLE) then PIN shuffle is +// disable +#define OS_SETTING_FEATURES_NO_PIN_SHUFFLE 0x2 +// if (os_settings[OS_SETTING_FEATURES] & OS_SETTING_FEATURES_BATT_IN_SIDE) then Battery percentage +// in side screen is enabled +#define OS_SETTING_FEATURES_BATT_IN_SIDE 0x4 /** - * Retrieve the value of a setting in a user specified buffer, with a max length, and return the effective returned length. + * Retrieve the value of a setting in a user specified buffer, with a max length, and return the + * effective returned length. */ -SYSCALL PERMISSION(APPLICATION_FLAG_BOLOS_SETTINGS) unsigned int os_setting_get(unsigned int setting_id, unsigned char* value PLENGTH(maxlen), unsigned int maxlen); +SYSCALL PERMISSION(APPLICATION_FLAG_BOLOS_SETTINGS) +unsigned int os_setting_get(unsigned int setting_id, + unsigned char *value PLENGTH(maxlen), + unsigned int maxlen); /** - * Define a setting's value from a user buffer and its length. In case of error, a throw is executed. + * Define a setting's value from a user buffer and its length. In case of error, a throw is + * executed. */ -SYSCALL PERMISSION(APPLICATION_FLAG_BOLOS_SETTINGS) void os_setting_set(unsigned int setting_id, unsigned char* value PLENGTH(length), unsigned int length); +SYSCALL PERMISSION(APPLICATION_FLAG_BOLOS_SETTINGS) void os_setting_set(unsigned int setting_id, + unsigned char *value + PLENGTH(length), + unsigned int length); #ifdef HAVE_LANGUAGE_PACK // Shift preferences settings (could be needed after an update) @@ -130,7 +144,7 @@ void os_setting_update(void); // Prototypes for language helper functions unsigned int os_setting_get_language(void); -void os_setting_set_language(unsigned int language); -#endif //HAVE_LANGUAGE_PACK +void os_setting_set_language(unsigned int language); +#endif // HAVE_LANGUAGE_PACK -unsigned int os_setting_get_default_device_name(unsigned char* buffer, unsigned int maxlength); +unsigned int os_setting_get_default_device_name(unsigned char *buffer, unsigned int maxlength); diff --git a/include/os_task.h b/include/os_task.h index 615b34ad6..002c5cd9e 100644 --- a/include/os_task.h +++ b/include/os_task.h @@ -8,20 +8,20 @@ typedef unsigned char bolos_task_status_t; enum task_unsecure_id_e { - TASK_BOLOS=0, // can call os - TASK_SYSCALL, // can call os - TASK_USERTASKS_START, - // disabled for now // TASK_USER_UX, // must call syscalls to reach os, locked in ux ram - TASK_USER=TASK_USERTASKS_START, // must call syscalls to reach os, locked in app ram - TASK_SUBTASKS_START, - TASK_SUBTASK_0=TASK_SUBTASKS_START, + TASK_BOLOS = 0, // can call os + TASK_SYSCALL, // can call os + TASK_USERTASKS_START, + // disabled for now // TASK_USER_UX, // must call syscalls to reach os, locked in ux ram + TASK_USER = TASK_USERTASKS_START, // must call syscalls to reach os, locked in app ram + TASK_SUBTASKS_START, + TASK_SUBTASK_0 = TASK_SUBTASKS_START, #ifdef TARGET_NANOX - TASK_SUBTASK_1, - TASK_SUBTASK_2, - TASK_SUBTASK_3, -#endif // TARGET_NANOX - TASK_BOLOS_UX, - TASK_MAXCOUNT, // must be last in the structure + TASK_SUBTASK_1, + TASK_SUBTASK_2, + TASK_SUBTASK_3, +#endif // TARGET_NANOX + TASK_BOLOS_UX, + TASK_MAXCOUNT, // must be last in the structure }; // execute the given application index in the registry, this function kills the current app task @@ -35,7 +35,7 @@ SYSCALL void __attribute__((noreturn)) os_sched_exit(bolos_task_status_t exit_co #endif // returns true when the given task is running, false else. - SYSCALL bolos_bool_t os_sched_is_running(unsigned int task_idx); +SYSCALL bolos_bool_t os_sched_is_running(unsigned int task_idx); /** * Retrieve the last status issued by a task using either yield or exit. @@ -75,19 +75,19 @@ SUDOCALL unsigned int os_sched_current_task(void); * @param ram0 /ram0_length the first RAM segment description * @param stack /stack_length the task's stack RAM segment description */ - SYSCALL unsigned int os_sched_create(void * main PLENGTH(4), -void * nvram PLENGTH(nvram_length), -unsigned int nvram_length, -void * ram0 PLENGTH(ram0_length), -unsigned int ram0_length, -void * stack PLENGTH(stack_length), -unsigned int stack_length); +SYSCALL unsigned int os_sched_create(void *main PLENGTH(4), + void *nvram PLENGTH(nvram_length), + unsigned int nvram_length, + void *ram0 PLENGTH(ram0_length), + unsigned int ram0_length, + void *stack PLENGTH(stack_length), + unsigned int stack_length); // kill a task SYSCALL void os_sched_kill(unsigned int taskidx); typedef struct { - void (*asynchmodal_end_callback) (unsigned int ux_status); + void (*asynchmodal_end_callback)(unsigned int ux_status); } bolos_ux_asynch_callback_t; extern bolos_ux_asynch_callback_t G_io_asynch_ux_callback; diff --git a/include/os_types.h b/include/os_types.h index d10a1bc72..608032630 100644 --- a/include/os_types.h +++ b/include/os_types.h @@ -12,9 +12,10 @@ typedef uint8_t bolos_bool_t; #define BOLOS_UX_CANCEL 0x55 #define BOLOS_UX_ERROR 0xD6 -/* Value returned by os_ux to notify the application that the processed event must be discarded and not processed by the application. Generally due to handling of power management/dim/locking */ -#define BOLOS_UX_IGNORE 0x97 +/* Value returned by os_ux to notify the application that the processed event must be discarded and + * not processed by the application. Generally due to handling of power management/dim/locking */ +#define BOLOS_UX_IGNORE 0x97 // a modal has destroyed the display, app needs to redraw its screen -#define BOLOS_UX_REDRAW 0x69 +#define BOLOS_UX_REDRAW 0x69 // ux has not finished processing yet (not a final status) #define BOLOS_UX_CONTINUE 0 diff --git a/include/os_utils.h b/include/os_utils.h index d317da4e2..bab06f013 100644 --- a/include/os_utils.h +++ b/include/os_utils.h @@ -6,58 +6,73 @@ /** * Helper to perform compilation time assertions */ -#if ! defined(SYSCALL_GENERATE) && (defined(__clang__) || (__GNUC__ > 4 || (__GNUC__ == 4 && (__GNUC_MINOR__ >= 6))) ) -#define CCASSERT(id, predicate) _Static_assert(predicate, #id) +#if !defined(SYSCALL_GENERATE) \ + && (defined(__clang__) || (__GNUC__ > 4 || (__GNUC__ == 4 && (__GNUC_MINOR__ >= 6)))) +#define CCASSERT(id, predicate) _Static_assert(predicate, #id) #else -#define CCASSERT(id, predicate) __x_CCASSERT_LINE(predicate, id, __LINE__) +#define CCASSERT(id, predicate) __x_CCASSERT_LINE(predicate, id, __LINE__) #define __x_CCASSERT_LINE(predicate, file, line) __xx_CCASSERT_LINE(predicate, file, line) -#define __xx_CCASSERT_LINE(predicate, file, line) typedef char CCASSERT_ ## file ## _line_## line [((predicate)?1:-1)] +#define __xx_CCASSERT_LINE(predicate, file, line) \ + typedef char CCASSERT_##file##_line_##line[((predicate) ? 1 : -1)] #endif -#define U2(hi,lo) ((((hi)&0xFFu)<<8) | ((lo)&0xFFu)) -#define U4(hi3, hi2, lo1,lo0) ((((hi3)&0xFFu)<<24) | (((hi2)&0xFFu)<<16) | (((lo1)&0xFFu)<<8) | ((lo0)&0xFFu)) -static inline uint16_t U2BE(const uint8_t *buf, size_t off) { - return (buf[off] << 8) | buf[off + 1]; +#define U2(hi, lo) ((((hi) &0xFFu) << 8) | ((lo) &0xFFu)) +#define U4(hi3, hi2, lo1, lo0) \ + ((((hi3) &0xFFu) << 24) | (((hi2) &0xFFu) << 16) | (((lo1) &0xFFu) << 8) | ((lo0) &0xFFu)) +static inline uint16_t U2BE(const uint8_t *buf, size_t off) +{ + return (buf[off] << 8) | buf[off + 1]; } -static inline uint32_t U4BE(const uint8_t *buf, size_t off) { - return (((uint32_t)buf[off]) << 24) | (buf[off + 1] << 16) | (buf[off + 2] << 8) | buf[off + 3]; +static inline uint32_t U4BE(const uint8_t *buf, size_t off) +{ + return (((uint32_t) buf[off]) << 24) | (buf[off + 1] << 16) | (buf[off + 2] << 8) + | buf[off + 3]; } -static inline uint16_t U2LE(const uint8_t *buf, size_t off) { - return (buf[off + 1] << 8) | buf[off]; +static inline uint16_t U2LE(const uint8_t *buf, size_t off) +{ + return (buf[off + 1] << 8) | buf[off]; } -static inline uint32_t U4LE(const uint8_t *buf, size_t off) { - return (((uint32_t)buf[off + 3]) << 24) | (buf[off + 2] << 16) | (buf[off + 1] << 8) | buf[off]; +static inline uint32_t U4LE(const uint8_t *buf, size_t off) +{ + return (((uint32_t) buf[off + 3]) << 24) | (buf[off + 2] << 16) | (buf[off + 1] << 8) + | buf[off]; } -static inline void U2BE_ENCODE(uint8_t *buf, size_t off, uint32_t value) { - buf[off + 0] = (value >> 8) & 0xFF; - buf[off + 1] = value & 0xFF; +static inline void U2BE_ENCODE(uint8_t *buf, size_t off, uint32_t value) +{ + buf[off + 0] = (value >> 8) & 0xFF; + buf[off + 1] = value & 0xFF; } -static inline void U4BE_ENCODE(uint8_t *buf, size_t off, uint32_t value) { - buf[off + 0] = (value >> 24) & 0xFF; - buf[off + 1] = (value >> 16) & 0xFF; - buf[off + 2] = (value >> 8) & 0xFF; - buf[off + 3] = value & 0xFF; +static inline void U4BE_ENCODE(uint8_t *buf, size_t off, uint32_t value) +{ + buf[off + 0] = (value >> 24) & 0xFF; + buf[off + 1] = (value >> 16) & 0xFF; + buf[off + 2] = (value >> 8) & 0xFF; + buf[off + 3] = value & 0xFF; } -static inline void U2LE_ENCODE(uint8_t *buf, size_t off, uint32_t value) { - buf[off + 1] = (value >> 8) & 0xFF; - buf[off + 0] = value & 0xFF; +static inline void U2LE_ENCODE(uint8_t *buf, size_t off, uint32_t value) +{ + buf[off + 1] = (value >> 8) & 0xFF; + buf[off + 0] = value & 0xFF; } -static inline void U4LE_ENCODE(uint8_t *buf, size_t off, uint32_t value) { - buf[off + 3] = (value >> 24) & 0xFF; - buf[off + 2] = (value >> 16) & 0xFF; - buf[off + 1] = (value >> 8) & 0xFF; - buf[off + 0] = value & 0xFF; +static inline void U4LE_ENCODE(uint8_t *buf, size_t off, uint32_t value) +{ + buf[off + 3] = (value >> 24) & 0xFF; + buf[off + 2] = (value >> 16) & 0xFF; + buf[off + 1] = (value >> 8) & 0xFF; + buf[off + 0] = value & 0xFF; } -void u4be_encode(unsigned char* buffer, unsigned int offset, unsigned int value); -void u4le_encode(unsigned char* buffer, unsigned int offset, unsigned int value); +void u4be_encode(unsigned char *buffer, unsigned int offset, unsigned int value); +void u4le_encode(unsigned char *buffer, unsigned int offset, unsigned int value); int bytes_to_hex(char *out, size_t outl, const void *value, size_t len); int bytes_to_lowercase_hex(char *out, size_t outl, const void *value, size_t len); -#define ARRAYLEN(array) (sizeof(array)/sizeof(array[0])) -#define INARRAY(elementptr, array) ((unsigned int)elementptr >= (unsigned int)array && (unsigned int)elementptr < ((unsigned int)array)+sizeof(array)) +#define ARRAYLEN(array) (sizeof(array) / sizeof(array[0])) +#define INARRAY(elementptr, array) \ + ((unsigned int) elementptr >= (unsigned int) array \ + && (unsigned int) elementptr < ((unsigned int) array) + sizeof(array)) /* ----------------------------------------------------------------------- */ /* - OS FUNCTIONS - */ @@ -65,23 +80,27 @@ int bytes_to_lowercase_hex(char *out, size_t outl, const void *value, size_t len #define os_swap_u16(u16) __builtin_bswap16(u16) #define os_swap_u32(u32) __builtin_bswap32(u32) -void os_memset4(void* dst, unsigned int initval, unsigned int nbintval); -void os_xor(void * dst, void * src1, void * src2, unsigned int length); +void os_memset4(void *dst, unsigned int initval, unsigned int nbintval); +void os_xor(void *dst, void *src1, void *src2, unsigned int length); // Secure memory comparison -char os_secure_memcmp(const void *src1, const void* src2, size_t length); +char os_secure_memcmp(const void *src1, const void *src2, size_t length); // Alignement-related -#define UPPER_ALIGN(adr, align, type) (type)((type)((type)(adr)+(type)((type)((type)MAX((type)(align),(type)1UL))-(type)1UL))&(type)(~(type)((type)((type)MAX(((type)align),(type)1UL))-(type)1UL))) -#define LOWER_ALIGN(adr, align, type) ((type)(adr)&(type)((type)~(type)(((type)MAX((type)(align),(type)1UL))-(type)1UL))) +#define UPPER_ALIGN(adr, align, type) \ + (type)((type) ((type) (adr) \ + + (type) ((type) ((type) MAX((type) (align), (type) 1UL)) - (type) 1UL)) \ + & (type) (~(type) ((type) ((type) MAX(((type) align), (type) 1UL)) - (type) 1UL))) +#define LOWER_ALIGN(adr, align, type) \ + ((type) (adr) & (type) ((type) ~(type) (((type) MAX((type) (align), (type) 1UL)) - (type) 1UL))) #ifdef macro_offsetof -#define offsetof(type, field) ((unsigned int)&(((type*)NULL)->field)) +#define offsetof(type, field) ((unsigned int) &(((type *) NULL)->field)) #endif void *os_memmove(void *dest, const void *src, size_t n) DEPRECATED; void *os_memcpy(void *dest, const void *src, size_t n) DEPRECATED; -int os_memcmp(const void *s1, const void *s2, size_t n) DEPRECATED; +int os_memcmp(const void *s1, const void *s2, size_t n) DEPRECATED; void *os_memset(void *s, int c, size_t n) DEPRECATED; // This call will reset the value of the entire BSS segment diff --git a/include/os_ux.h b/include/os_ux.h index 6530c9b89..90622b47f 100644 --- a/include/os_ux.h +++ b/include/os_ux.h @@ -17,93 +17,95 @@ // Enumeration of the UX events usable by the UX library. typedef enum bolos_ux_e { - BOLOS_UX_INITIALIZE = 0, - BOLOS_UX_EVENT, - BOLOS_UX_KEYBOARD, - BOLOS_UX_WAKE_UP, - BOLOS_UX_STATUS_BAR, + BOLOS_UX_INITIALIZE = 0, + BOLOS_UX_EVENT, + BOLOS_UX_KEYBOARD, + BOLOS_UX_WAKE_UP, + BOLOS_UX_STATUS_BAR, - BOLOS_UX_VALIDATE_PIN, - BOLOS_UX_ASYNCHMODAL_PAIRING_REQUEST, // ask the ux to display a modal to accept/reject the current pairing request - BOLOS_UX_ASYNCHMODAL_PAIRING_CANCEL, - BOLOS_UX_LAST_ID, + BOLOS_UX_VALIDATE_PIN, + BOLOS_UX_ASYNCHMODAL_PAIRING_REQUEST, // ask the ux to display a modal to accept/reject the + // current pairing request + BOLOS_UX_ASYNCHMODAL_PAIRING_CANCEL, + BOLOS_UX_LAST_ID, } bolos_ux_t; // Structure that defines the parameters to exchange with the BOLOS UX application typedef struct bolos_ux_params_s { - // Event identifier. - bolos_ux_t ux_id; - // length of parameters in the u union to be copied during the syscall. - unsigned int len; + // Event identifier. + bolos_ux_t ux_id; + // length of parameters in the u union to be copied during the syscall. + unsigned int len; #if defined(HAVE_BLE) || defined(HAVE_KEYBOARD_UX) - union { - // Structure for the lib ux. + union { + // Structure for the lib ux. #if defined(HAVE_KEYBOARD_UX) - struct { - unsigned int keycode; + struct { + unsigned int keycode; #define BOLOS_UX_MODE_UPPERCASE 0 #define BOLOS_UX_MODE_LOWERCASE 1 #define BOLOS_UX_MODE_SYMBOLS 2 -#define BOLOS_UX_MODE_COUNT 3 // number of keyboard modes - unsigned int mode; - // + 1 EOS (0) +#define BOLOS_UX_MODE_COUNT 3 // number of keyboard modes + unsigned int mode; + // + 1 EOS (0) #define BOLOS_UX_KEYBOARD_TEXT_BUFFER_SIZE 32 - char entered_text[BOLOS_UX_KEYBOARD_TEXT_BUFFER_SIZE+1]; - } keyboard; -#endif // HAVE_KEYBOARD_UX + char entered_text[BOLOS_UX_KEYBOARD_TEXT_BUFFER_SIZE + 1]; + } keyboard; +#endif // HAVE_KEYBOARD_UX -# if defined(HAVE_BLE) - struct { - enum { - BOLOS_UX_ASYNCHMODAL_PAIRING_REQUEST_PASSKEY, - BOLOS_UX_ASYNCHMODAL_PAIRING_REQUEST_NUMCOMP, - } type; - unsigned int pairing_info_len; - char pairing_info[16]; - } pairing_request; +#if defined(HAVE_BLE) + struct { + enum { + BOLOS_UX_ASYNCHMODAL_PAIRING_REQUEST_PASSKEY, + BOLOS_UX_ASYNCHMODAL_PAIRING_REQUEST_NUMCOMP, + } type; + unsigned int pairing_info_len; + char pairing_info[16]; + } pairing_request; - struct { - enum { - BOLOS_UX_ASYNCHMODAL_PAIRING_STATUS_CONFIRM_CODE_YES, - BOLOS_UX_ASYNCHMODAL_PAIRING_STATUS_CONFIRM_CODE_NO, - BOLOS_UX_ASYNCHMODAL_PAIRING_STATUS_ACCEPT_PASSKEY, - BOLOS_UX_ASYNCHMODAL_PAIRING_STATUS_CANCEL_PASSKEY, - BOLOS_UX_ASYNCHMODAL_PAIRING_STATUS_SUCCESS, - BOLOS_UX_ASYNCHMODAL_PAIRING_STATUS_TIMEOUT, - BOLOS_UX_ASYNCHMODAL_PAIRING_STATUS_FAILED, - BOLOS_UX_ASYNCHMODAL_PAIRING_STATUS_CANCELLED_FROM_REMOTE, - } pairing_ok; - } pairing_status; // sent in BOLOS_UX_ASYNCHMODAL_PAIRING_CANCEL message -# endif // HAVE_BLE - } u; -#endif // defined(HAVE_BLE) || defined(HAVE_KEYBOARD_UX) + struct { + enum { + BOLOS_UX_ASYNCHMODAL_PAIRING_STATUS_CONFIRM_CODE_YES, + BOLOS_UX_ASYNCHMODAL_PAIRING_STATUS_CONFIRM_CODE_NO, + BOLOS_UX_ASYNCHMODAL_PAIRING_STATUS_ACCEPT_PASSKEY, + BOLOS_UX_ASYNCHMODAL_PAIRING_STATUS_CANCEL_PASSKEY, + BOLOS_UX_ASYNCHMODAL_PAIRING_STATUS_SUCCESS, + BOLOS_UX_ASYNCHMODAL_PAIRING_STATUS_TIMEOUT, + BOLOS_UX_ASYNCHMODAL_PAIRING_STATUS_FAILED, + BOLOS_UX_ASYNCHMODAL_PAIRING_STATUS_CANCELLED_FROM_REMOTE, + } pairing_ok; + } pairing_status; // sent in BOLOS_UX_ASYNCHMODAL_PAIRING_CANCEL message +#endif // HAVE_BLE + } u; +#endif // defined(HAVE_BLE) || defined(HAVE_KEYBOARD_UX) } bolos_ux_params_t; -#endif // !defined(HAVE_BOLOS) +#endif // !defined(HAVE_BOLOS) /* ----------------------------------------------------------------------- */ /* - UX-RELATED - */ /* ----------------------------------------------------------------------- */ #if defined(BOLOS_TEST_APDUS_UX) void bolos_test_ux_apdu(void); -#endif //defined(BOLOS_TEST_APDUS_UX) +#endif // defined(BOLOS_TEST_APDUS_UX) // return !0 when ux scenario has ended, else 0 -// while not ended, all display/touch/ticker and other events are to be processed by the ux. only io is not processed. -// when returning !0 the application must send a general status (or continue its command flow) -SYSCALL TASKSWITCH unsigned int os_ux(bolos_ux_params_t* params PLENGTH(sizeof(bolos_ux_params_t))); +// while not ended, all display/touch/ticker and other events are to be processed by the ux. only io +// is not processed. when returning !0 the application must send a general status (or continue its +// command flow) +SYSCALL TASKSWITCH unsigned int os_ux(bolos_ux_params_t *params PLENGTH(sizeof(bolos_ux_params_t))); // read parameters back from the UX app. useful to read keyboard type or such -SYSCALL void os_ux_result(bolos_ux_params_t* params PLENGTH(sizeof(bolos_ux_params_t))); +SYSCALL void os_ux_result(bolos_ux_params_t *params PLENGTH(sizeof(bolos_ux_params_t))); // process all possible messages while waiting for a ux to finish, // unprocessed messages are replied with a generic general status // when returning the application must send a general status (or continue its command flow) -unsigned int os_ux_blocking(bolos_ux_params_t* params); -#endif // !defined(APP_UX) +unsigned int os_ux_blocking(bolos_ux_params_t *params); +#endif // !defined(APP_UX) #ifdef HAVE_BLE SYSCALL void os_ux_set_status(unsigned int ux_id, unsigned int status); SYSCALL unsigned int os_ux_get_status(unsigned int ux_id); -#endif // HAVE_BLE +#endif // HAVE_BLE diff --git a/include/ox.h b/include/ox.h index 716818125..27eec298c 100644 --- a/include/ox.h +++ b/include/ox.h @@ -1,20 +1,20 @@ /******************************************************************************* -* Ledger Nano S - Secure firmware -* (c) 2022 Ledger -* -* Licensed under the Apache License, Version 2.0 (the "License"); -* you may not use this file except in compliance with the License. -* You may obtain a copy of the License at -* -* http://www.apache.org/licenses/LICENSE-2.0 -* -* Unless required by applicable law or agreed to in writing, software -* distributed under the License is distributed on an "AS IS" BASIS, -* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -* See the License for the specific language governing permissions and -* limitations under the License. -********************************************************************************/ + * Ledger Nano S - Secure firmware + * (c) 2022 Ledger + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + ********************************************************************************/ /** * @file ox.h @@ -37,6 +37,6 @@ #include "ox_rng.h" #if defined(HAVE_VSS) #include "ox_vss.h" -#endif // HAVE_VSS +#endif // HAVE_VSS -#endif // OX_H +#endif // OX_H diff --git a/include/ox_aes.h b/include/ox_aes.h index ee4ef516a..25d7d2519 100644 --- a/include/ox_aes.h +++ b/include/ox_aes.h @@ -1,20 +1,20 @@ /******************************************************************************* -* Ledger Nano S - Secure firmware -* (c) 2022 Ledger -* -* Licensed under the Apache License, Version 2.0 (the "License"); -* you may not use this file except in compliance with the License. -* You may obtain a copy of the License at -* -* http://www.apache.org/licenses/LICENSE-2.0 -* -* Unless required by applicable law or agreed to in writing, software -* distributed under the License is distributed on an "AS IS" BASIS, -* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -* See the License for the specific language governing permissions and -* limitations under the License. -********************************************************************************/ + * Ledger Nano S - Secure firmware + * (c) 2022 Ledger + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + ********************************************************************************/ /** * @file ox_aes.h @@ -39,15 +39,16 @@ * It is basically divided into: * - **cryptography API** which consists of signature algorithms, hash functions, message * authentication codes and encryption algorithms - * - **syscalls** which enable computations for GF(p) and GF(2n) arithmetic and efficient - * implementation of elliptic curves. + * - **syscalls** which enable computations for GF(p) and GF(2n) arithmetic + * and efficient implementation of elliptic curves. * * Here is a non-exhaustive list of supported algorithms: * - AES in various modes * - ECDSA with a random or deterministic nonce * - EDDSA * - ECDH - * - Schnorr signature with different implementations, especially the one used for Zilliqa and BIP-0340 + * - Schnorr signature with different implementations, especially the one used for Zilliqa and + * BIP-0340 * - Multiple hash functions from SHA-2 and SHA-3 families as well as extendable output functions * (SHAKE-128 and SHAKE-256) * - RIPEMD-160 @@ -75,8 +76,8 @@ * @details Such container should be initialized with #cx_aes_init_key_no_throw. */ struct cx_aes_key_s { - size_t size; ///< key size - uint8_t keys[32]; ///< key value + size_t size; ///< key size + uint8_t keys[32]; ///< key value }; /** Convenience type. See #cx_aes_key_s. */ typedef struct cx_aes_key_s cx_aes_key_t; @@ -92,7 +93,8 @@ typedef struct cx_aes_key_s cx_aes_key_t; * - CX_OK on success * - CX_INVALID_PARAMETER */ -SYSCALL cx_err_t cx_aes_set_key_hw(const cx_aes_key_t *key PLENGTH(sizeof(cx_aes_key_t)), uint32_t mode); +SYSCALL cx_err_t cx_aes_set_key_hw(const cx_aes_key_t *key PLENGTH(sizeof(cx_aes_key_t)), + uint32_t mode); /** * @brief Resets the AES context. @@ -110,6 +112,7 @@ SYSCALL void cx_aes_reset_hw(void); * - CX_OK on success * - INVALID_PARAMETER */ -SYSCALL cx_err_t cx_aes_block_hw(const unsigned char *inblock PLENGTH(16), unsigned char *outblock PLENGTH(16)); +SYSCALL cx_err_t cx_aes_block_hw(const unsigned char *inblock PLENGTH(16), + unsigned char *outblock PLENGTH(16)); #endif diff --git a/include/ox_bls.h b/include/ox_bls.h index 418f8e56d..6467cbf38 100644 --- a/include/ox_bls.h +++ b/include/ox_bls.h @@ -32,7 +32,8 @@ * The first bit of mode indicates whether the secret should be derived * or used as is for the private key. * - * @param[in] secret Pointer to either random bytes used to derive the private key or the private key itself. + * @param[in] secret Pointer to either random bytes used to derive the private key or the + * private key itself. * * @param[in] secret_len Length of the secret which should be at most 32 bytes. * @@ -47,7 +48,8 @@ * * @param[in] private_key Pointer to the private key structure. * - * @param[in] public_key Pointer to the public key. This is NULL for 'basic' and 'proof of possession' schemes. + * @param[in] public_key Pointer to the public key. This is NULL for 'basic' and 'proof of + * possession' schemes. * * @param[in] public_key_len Length of the public key. * @@ -59,13 +61,16 @@ * - CX_EC_INVALID_POINT * - CX_EC_INFINITE_POINT */ -SYSCALL cx_err_t cx_bls12381_key_gen(uint8_t mode, - const uint8_t *secret, size_t secret_len, - const uint8_t *salt, size_t salt_len, - uint8_t *key_info, size_t key_info_len, +SYSCALL cx_err_t cx_bls12381_key_gen(uint8_t mode, + const uint8_t *secret, + size_t secret_len, + const uint8_t *salt, + size_t salt_len, + uint8_t *key_info, + size_t key_info_len, cx_ecfp_384_private_key_t *private_key, - uint8_t *public_key, - size_t public_key_len); + uint8_t *public_key, + size_t public_key_len); /** * @brief Hash a message to be signed with BLS12-381 signature scheme. @@ -91,30 +96,33 @@ SYSCALL cx_err_t cx_bls12381_key_gen(uint8_t mode, * - CX_INVALID_PARAMETER * - CX_MEMORY_FULL */ -SYSCALL cx_err_t cx_hash_to_field(const uint8_t *msg, size_t msg_len, - const uint8_t *dst, size_t dst_len, - uint8_t *hash, size_t hash_len); +SYSCALL cx_err_t cx_hash_to_field(const uint8_t *msg, + size_t msg_len, + const uint8_t *dst, + size_t dst_len, + uint8_t *hash, + size_t hash_len); /** * @brief Sign the hash of a message. * - * @details BLS signature with the curve BLS12-381-G2. The message must be hash beforehand with #cx_hash_to_field. + * @details BLS signature with the curve BLS12-381-G2. The message must be hash beforehand with + * #cx_hash_to_field. * - * @param[in] key Private key. The private key must be initialized with #cx_ecfp_init_private_key_no_throw - * given a 32-byte raw key. + * @param[in] key Private key. The private key must be initialized with + * #cx_ecfp_init_private_key_no_throw given a 32-byte raw key. * * @param[in] message Hash of the message, result of #cx_hash_to_field. * * @param[in] message_len Length of the hash. This must be 192 bytes. * * @param[out] signature Compressed signature: only the x-coordinate of the point is returned. - * The most-significant three bits of the signature are used to unambiguously - * determine the y-coordinate among the two possible choices. - * The fist bit is always 1 to indicate that the signature is in compressed form. - * The second bit is set iff the result point is the point at infinity, i.e. all - * of the bits of signature must be 0. - * The third bit is set iff the y-coordinate is greater than (p-1)/2 where - * p = 0x1a0111ea397fe69a4b1ba7b6434bacd764774b84f38512bf6730d2a0f6b0f6241eabfffeb153ffffb9feffffffffaaab. + * The most-significant three bits of the signature are used to + * unambiguously determine the y-coordinate among the two possible choices. The fist bit is always 1 + * to indicate that the signature is in compressed form. The second bit is set iff the result point + * is the point at infinity, i.e. all of the bits of signature must be 0. The third bit is set iff + * the y-coordinate is greater than (p-1)/2 where p = + * 0x1a0111ea397fe69a4b1ba7b6434bacd764774b84f38512bf6730d2a0f6b0f6241eabfffeb153ffffb9feffffffffaaab. * * @param[in] signature_len Length of the signature. This must be 96 bytes. * @@ -124,10 +132,10 @@ SYSCALL cx_err_t cx_hash_to_field(const uint8_t *msg, size_t msg_len, * - CX_INVALID_PARAMETER */ SYSCALL cx_err_t ox_bls12381_sign(const cx_ecfp_384_private_key_t *key, - const uint8_t * message, - size_t message_len, - uint8_t * signature, - size_t signature_len); + const uint8_t *message, + size_t message_len, + uint8_t *signature, + size_t signature_len); /** * @brief Aggregate multiple signatures. @@ -151,8 +159,11 @@ SYSCALL cx_err_t ox_bls12381_sign(const cx_ecfp_384_private_key_t *key, * - CX_INTERNAL_ERROR * - CX_INVALID_PARAMETER */ -SYSCALL cx_err_t cx_bls12381_aggregate(const uint8_t *in, size_t in_len, bool first, - uint8_t *aggregated_signature, size_t signature_len); +SYSCALL cx_err_t cx_bls12381_aggregate(const uint8_t *in, + size_t in_len, + bool first, + uint8_t *aggregated_signature, + size_t signature_len); -#endif // HAVE_BLS -#endif // OX_BLS_H +#endif // HAVE_BLS +#endif // OX_BLS_H diff --git a/include/ox_bn.h b/include/ox_bn.h index ced996a10..9ba70f438 100644 --- a/include/ox_bn.h +++ b/include/ox_bn.h @@ -1,20 +1,20 @@ /******************************************************************************* -* Ledger Nano S - Secure firmware -* (c) 2022 Ledger -* -* Licensed under the Apache License, Version 2.0 (the "License"); -* you may not use this file except in compliance with the License. -* You may obtain a copy of the License at -* -* http://www.apache.org/licenses/LICENSE-2.0 -* -* Unless required by applicable law or agreed to in writing, software -* distributed under the License is distributed on an "AS IS" BASIS, -* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -* See the License for the specific language governing permissions and -* limitations under the License. -********************************************************************************/ + * Ledger Nano S - Secure firmware + * (c) 2022 Ledger + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + ********************************************************************************/ /** * @file ox_bn.h @@ -41,11 +41,10 @@ * * @details A BN size shall be a multiple of this. */ -#define CX_BN_WORD_ALIGNEMENT 16 +#define CX_BN_WORD_ALIGNEMENT 16 /* high level, public and common */ - /* ========================================================================= */ /* === TYPES === */ /* ========================================================================= */ @@ -63,7 +62,6 @@ typedef struct { cx_bn_t h; ///< @private Second Montgomery constant } cx_bn_mont_ctx_t; - /* ========================================================================= */ /* === CONFIG === */ /* ========================================================================= */ @@ -141,7 +139,6 @@ cx_err_t cx_bn_locked(void); */ SYSCALL cx_err_t cx_bn_alloc(cx_bn_t *x PLENGTH(sizeof(cx_bn_t)), size_t nbytes); - /** * @brief Allocates memory for a new BN and * initializes it with the specified value. @@ -163,7 +160,10 @@ SYSCALL cx_err_t cx_bn_alloc(cx_bn_t *x PLENGTH(sizeof(cx_bn_t)), size_t nbytes) * - CX_BN_MEMORY_FULL * - CX_BN_INVALID_PARAMETER_SIZE */ -SYSCALL cx_err_t cx_bn_alloc_init(cx_bn_t *x PLENGTH(sizeof(cx_bn_t)), size_t nbytes, const uint8_t *value PLENGTH(value_nbytes), size_t value_nbytes); +SYSCALL cx_err_t cx_bn_alloc_init(cx_bn_t *x PLENGTH(sizeof(cx_bn_t)), + size_t nbytes, + const uint8_t *value PLENGTH(value_nbytes), + size_t value_nbytes); /** * @brief Releases a BN and gives back its attached memory to the system. @@ -177,7 +177,6 @@ SYSCALL cx_err_t cx_bn_alloc_init(cx_bn_t *x PLENGTH(sizeof(cx_bn_t)), size_t n */ SYSCALL cx_err_t cx_bn_destroy(cx_bn_t *x PLENGTH(sizeof(cx_bn_t))); - /** * @brief Gets the size in bytes of a BN. * @@ -191,7 +190,6 @@ SYSCALL cx_err_t cx_bn_destroy(cx_bn_t *x PLENGTH(sizeof(cx_bn_t))); */ SYSCALL cx_err_t cx_bn_nbytes(const cx_bn_t x, size_t *nbytes); - /* ========================================================================= */ /* === R/W === */ /* ========================================================================= */ @@ -209,8 +207,9 @@ SYSCALL cx_err_t cx_bn_nbytes(const cx_bn_t x, size_t *nbytes); * - CX_BN_INVALID_PARAMETER_SIZE * - CX_BN_INVALID_PARAMETER_VALUE */ -SYSCALL cx_err_t cx_bn_init(cx_bn_t x, const uint8_t *value PLENGTH(value_nbytes), size_t value_nbytes); - +SYSCALL cx_err_t cx_bn_init(cx_bn_t x, + const uint8_t *value PLENGTH(value_nbytes), + size_t value_nbytes); /** * @brief Generates a random number and @@ -287,7 +286,6 @@ SYSCALL cx_err_t cx_bn_get_u32(const cx_bn_t x, uint32_t *n); */ SYSCALL cx_err_t cx_bn_export(const cx_bn_t x, uint8_t *bytes PLENGTH(nbytes), size_t nbytes); - /* ========================================================================= */ /* === TEST === */ /* ========================================================================= */ @@ -505,7 +503,6 @@ SYSCALL cx_err_t cx_bn_cnt_bits(cx_bn_t n, uint32_t *nbits); /* === NON MODULAR ARITHMETIC === */ /* ========================================================================= */ - /** * @brief Performs an addition **r = a + b**. * @@ -562,8 +559,6 @@ SYSCALL cx_err_t cx_bn_sub(cx_bn_t r, const cx_bn_t a, const cx_bn_t b); */ SYSCALL cx_err_t cx_bn_mul(cx_bn_t r, const cx_bn_t a, const cx_bn_t b); - - /* ========================================================================= */ /* === Z/pZ MODULAR ARITHMETIC === */ /* ========================================================================= */ @@ -724,7 +719,11 @@ SYSCALL cx_err_t cx_bn_mod_pow_bn(cx_bn_t r, const cx_bn_t a, const cx_bn_t e, c * - CX_INVALID_PARAMETER * - CX_MEMORY_FULL */ -SYSCALL cx_err_t cx_bn_mod_pow(cx_bn_t r, const cx_bn_t a, const uint8_t *e PLENGTH(e_len), uint32_t e_len, const cx_bn_t n); +SYSCALL cx_err_t cx_bn_mod_pow(cx_bn_t r, + const cx_bn_t a, + const uint8_t *e PLENGTH(e_len), + uint32_t e_len, + const cx_bn_t n); /** * @brief Performs a modular exponentiation **r = a^e mod n**. @@ -752,8 +751,11 @@ SYSCALL cx_err_t cx_bn_mod_pow(cx_bn_t r, const cx_bn_t a, const uint8_t *e PLEN * - CX_INVALID_PARAMETER * - CX_MEMORY_FULL */ -SYSCALL cx_err_t cx_bn_mod_pow2(cx_bn_t r, const cx_bn_t a, const uint8_t *e PLENGTH(e_len), uint32_t e_len, const cx_bn_t n); - +SYSCALL cx_err_t cx_bn_mod_pow2(cx_bn_t r, + const cx_bn_t a, + const uint8_t *e PLENGTH(e_len), + uint32_t e_len, + const cx_bn_t n); /** * @brief Computes the modular inverse **r = a^(-1) mod n**, @@ -799,9 +801,6 @@ SYSCALL cx_err_t cx_bn_mod_invert_nprime(cx_bn_t r, const cx_bn_t a, const cx_bn */ SYSCALL cx_err_t cx_bn_mod_u32_invert(cx_bn_t r, uint32_t a, cx_bn_t n); - - - /* ========================================================================= */ /* === MONTGOMERY MODULAR ARITHMETIC === */ /* ========================================================================= */ @@ -818,7 +817,8 @@ SYSCALL cx_err_t cx_bn_mod_u32_invert(cx_bn_t r, uint32_t a, cx_bn_t n); * - CX_NOT_LOCKED * - CX_MEMORY_FULL */ -SYSCALL cx_err_t cx_mont_alloc(cx_bn_mont_ctx_t *ctx PLENGTH(sizeof(cx_bn_mont_ctx_t )), size_t length); +SYSCALL cx_err_t cx_mont_alloc(cx_bn_mont_ctx_t *ctx PLENGTH(sizeof(cx_bn_mont_ctx_t)), + size_t length); /** * @brief Initializes a Montgomery context with the modulus. @@ -835,7 +835,8 @@ SYSCALL cx_err_t cx_mont_alloc(cx_bn_mont_ctx_t *ctx PLENGTH(sizeof(cx_bn_mont_c * - CX_INVALID_PARAMETER * - CX_MEMORY_FULL */ -SYSCALL cx_err_t cx_mont_init(cx_bn_mont_ctx_t *ctx PLENGTH(sizeof(cx_bn_mont_ctx_t )), const cx_bn_t n); +SYSCALL cx_err_t cx_mont_init(cx_bn_mont_ctx_t *ctx PLENGTH(sizeof(cx_bn_mont_ctx_t)), + const cx_bn_t n); /** * @brief Initializes a Montgomery context with the modulus and @@ -857,7 +858,9 @@ SYSCALL cx_err_t cx_mont_init(cx_bn_mont_ctx_t *ctx PLENGTH(sizeof(cx_bn_mont_ct * - CX_NOT_LOCKED * - CX_INVALID_PARAMETER */ -SYSCALL cx_err_t cx_mont_init2(cx_bn_mont_ctx_t *ctx PLENGTH(sizeof(cx_bn_mont_ctx_t )), const cx_bn_t n, const cx_bn_t h); +SYSCALL cx_err_t cx_mont_init2(cx_bn_mont_ctx_t *ctx PLENGTH(sizeof(cx_bn_mont_ctx_t)), + const cx_bn_t n, + const cx_bn_t h); /** * @brief Computes the Montgomery representation of a BN value. @@ -877,7 +880,10 @@ SYSCALL cx_err_t cx_mont_init2(cx_bn_mont_ctx_t *ctx PLENGTH(sizeof(cx_bn_mont_c * - CX_INVALID_PARAMETER * - CX_MEMORY_FULL */ -SYSCALL cx_err_t cx_mont_to_montgomery(cx_bn_t x, const cx_bn_t z, const cx_bn_mont_ctx_t *ctx PLENGTH(sizeof(cx_bn_mont_ctx_t ))); +SYSCALL cx_err_t +cx_mont_to_montgomery(cx_bn_t x, + const cx_bn_t z, + const cx_bn_mont_ctx_t *ctx PLENGTH(sizeof(cx_bn_mont_ctx_t))); /** * @brief Computes the normal representation of a BN value @@ -899,8 +905,10 @@ SYSCALL cx_err_t cx_mont_to_montgomery(cx_bn_t x, const cx_bn_t z, const cx_bn_m * - CX_INVALID_PARAMETER * - CX_MEMORY_FULL */ -SYSCALL cx_err_t cx_mont_from_montgomery(cx_bn_t z, const cx_bn_t x, const cx_bn_mont_ctx_t *ctx PLENGTH(sizeof(cx_bn_mont_ctx_t ))); - +SYSCALL cx_err_t +cx_mont_from_montgomery(cx_bn_t z, + const cx_bn_t x, + const cx_bn_mont_ctx_t *ctx PLENGTH(sizeof(cx_bn_mont_ctx_t))); /** * @brief Performs a Montgomery multiplication. @@ -921,7 +929,10 @@ SYSCALL cx_err_t cx_mont_from_montgomery(cx_bn_t z, const cx_bn_t x, const cx_bn * - CX_NOT_LOCKED * - CX_INVALID_PARAMETER */ -SYSCALL cx_err_t cx_mont_mul(cx_bn_t r, const cx_bn_t a, const cx_bn_t b, const cx_bn_mont_ctx_t *ctx PLENGTH(sizeof(cx_bn_mont_ctx_t ))); +SYSCALL cx_err_t cx_mont_mul(cx_bn_t r, + const cx_bn_t a, + const cx_bn_t b, + const cx_bn_mont_ctx_t *ctx PLENGTH(sizeof(cx_bn_mont_ctx_t))); /** * @brief Performs a modular exponentiation **r = a^e mod n**. @@ -948,7 +959,11 @@ SYSCALL cx_err_t cx_mont_mul(cx_bn_t r, const cx_bn_t a, const cx_bn_t b, const * - CX_INVALID_PARAMETER * - CX_MEMORY_FULL */ -SYSCALL cx_err_t cx_mont_pow(cx_bn_t r, const cx_bn_t a, const uint8_t *e PLENGTH(e_len), uint32_t e_len, const cx_bn_mont_ctx_t *ctx PLENGTH(sizeof(cx_bn_mont_ctx_t ))); +SYSCALL cx_err_t cx_mont_pow(cx_bn_t r, + const cx_bn_t a, + const uint8_t *e PLENGTH(e_len), + uint32_t e_len, + const cx_bn_mont_ctx_t *ctx PLENGTH(sizeof(cx_bn_mont_ctx_t))); /** * @brief Performs a modular exponentiation **r = a^e mod n**. @@ -973,7 +988,10 @@ SYSCALL cx_err_t cx_mont_pow(cx_bn_t r, const cx_bn_t a, const uint8_t *e PLENGT * - CX_INVALID_PARAMETER * - CX_MEMORY_FULL */ -SYSCALL cx_err_t cx_mont_pow_bn(cx_bn_t r, const cx_bn_t a, const cx_bn_t e, const cx_bn_mont_ctx_t *ctx PLENGTH(sizeof(cx_bn_mont_ctx_t ))); +SYSCALL cx_err_t cx_mont_pow_bn(cx_bn_t r, + const cx_bn_t a, + const cx_bn_t e, + const cx_bn_mont_ctx_t *ctx PLENGTH(sizeof(cx_bn_mont_ctx_t))); /** * @brief Computes the modular inverse **r = a^(-1) mod n** for @@ -996,15 +1014,15 @@ SYSCALL cx_err_t cx_mont_pow_bn(cx_bn_t r, const cx_bn_t a, const cx_bn_t e, con * - CX_INVALID_PARAMETER * - CX_MEMORY_FULL */ -SYSCALL cx_err_t cx_mont_invert_nprime(cx_bn_t r, const cx_bn_t a, const cx_bn_mont_ctx_t *ctx PLENGTH(sizeof(cx_bn_mont_ctx_t ))); - - +SYSCALL cx_err_t +cx_mont_invert_nprime(cx_bn_t r, + const cx_bn_t a, + const cx_bn_mont_ctx_t *ctx PLENGTH(sizeof(cx_bn_mont_ctx_t))); /* ========================================================================= */ /* === PRIME === */ /* ========================================================================= */ - /** * @brief Tests whether a BN value is a probable prime. * @@ -1054,7 +1072,6 @@ SYSCALL cx_err_t cx_bn_next_prime(cx_bn_t n); */ SYSCALL cx_err_t cx_bn_rng(cx_bn_t r, const cx_bn_t n); - /** * @brief Performs a multiplication over GF(2^n). * @@ -1076,7 +1093,10 @@ SYSCALL cx_err_t cx_bn_rng(cx_bn_t r, const cx_bn_t n); * - CX_INVALID_PARAMETER * - CX_MEMORY_FULL */ -SYSCALL cx_err_t cx_bn_gf2_n_mul(cx_bn_t bn_r, const cx_bn_t bn_a, const cx_bn_t bn_b, const cx_bn_t bn_n, const cx_bn_t bn_h); - +SYSCALL cx_err_t cx_bn_gf2_n_mul(cx_bn_t bn_r, + const cx_bn_t bn_a, + const cx_bn_t bn_b, + const cx_bn_t bn_n, + const cx_bn_t bn_h); #endif /* CX_BN_H */ diff --git a/include/ox_crc.h b/include/ox_crc.h index 74da55c78..8ab3d3f69 100644 --- a/include/ox_crc.h +++ b/include/ox_crc.h @@ -1,20 +1,20 @@ /******************************************************************************* -* Ledger Nano S - Secure firmware -* (c) 2022 Ledger -* -* Licensed under the Apache License, Version 2.0 (the "License"); -* you may not use this file except in compliance with the License. -* You may obtain a copy of the License at -* -* http://www.apache.org/licenses/LICENSE-2.0 -* -* Unless required by applicable law or agreed to in writing, software -* distributed under the License is distributed on an "AS IS" BASIS, -* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -* See the License for the specific language governing permissions and -* limitations under the License. -********************************************************************************/ + * Ledger Nano S - Secure firmware + * (c) 2022 Ledger + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + ********************************************************************************/ /** * @file ox_crc.h @@ -40,4 +40,4 @@ */ SYSCALL uint32_t cx_crc32_hw(const void *buf PLENGTH(len), size_t len); -#endif // OX_CRC_H +#endif // OX_CRC_H diff --git a/include/ox_ec.h b/include/ox_ec.h index 5ab9a62f1..09cd5fbaa 100644 --- a/include/ox_ec.h +++ b/include/ox_ec.h @@ -1,20 +1,20 @@ /******************************************************************************* -* Ledger Nano S - Secure firmware -* (c) 2022 Ledger -* -* Licensed under the Apache License, Version 2.0 (the "License"); -* you may not use this file except in compliance with the License. -* You may obtain a copy of the License at -* -* http://www.apache.org/licenses/LICENSE-2.0 -* -* Unless required by applicable law or agreed to in writing, software -* distributed under the License is distributed on an "AS IS" BASIS, -* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -* See the License for the specific language governing permissions and -* limitations under the License. -********************************************************************************/ + * Ledger Nano S - Secure firmware + * (c) 2022 Ledger + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + ********************************************************************************/ /** * @file ox_ec.h @@ -110,168 +110,171 @@ /** List of supported elliptic curves */ enum cx_curve_e { - /** Undefined curve */ - CX_CURVE_NONE, + /** Undefined curve */ + CX_CURVE_NONE, #ifdef HAVE_ECC_WEIERSTRASS - /* ------------------------ */ - /* --- Type Weierstrass --- */ - /* ------------------------ */ - /** Low limit (not included) of Weierstrass curve ID */ - CX_CURVE_WEIERSTRASS_START = 0x20, + /* ------------------------ */ + /* --- Type Weierstrass --- */ + /* ------------------------ */ + /** Low limit (not included) of Weierstrass curve ID */ + CX_CURVE_WEIERSTRASS_START = 0x20, #ifdef HAVE_SECP256K1_CURVE - /** Secp256k1 */ - CX_CURVE_SECP256K1 = 0x21, + /** Secp256k1 */ + CX_CURVE_SECP256K1 = 0x21, /** Allowed identifier for Secp256k1*/ #define CX_CURVE_256K1 CX_CURVE_SECP256K1 #endif #ifdef HAVE_SECP256R1_CURVE - /** Secp256r1 */ - CX_CURVE_SECP256R1 = 0x22, + /** Secp256r1 */ + CX_CURVE_SECP256R1 = 0x22, /** Legacy identifier for Secp256r1 */ -#define CX_CURVE_256R1 CX_CURVE_SECP256R1 +#define CX_CURVE_256R1 CX_CURVE_SECP256R1 /** Legacy identifier for Secp256r1 */ #define CX_CURVE_NISTP256 CX_CURVE_SECP256R1 #endif #ifdef HAVE_SECP384R1_CURVE - /** Secp384r1 */ - CX_CURVE_SECP384R1 = 0x23, + /** Secp384r1 */ + CX_CURVE_SECP384R1 = 0x23, /** Allowed identifier for Secp384r1 */ #define CX_CURVE_NISTP384 CX_CURVE_SECP384R1 #endif #ifdef HAVE_SECP521R1_CURVE - /** Secp521r1 */ - CX_CURVE_SECP521R1 = 0x24, + /** Secp521r1 */ + CX_CURVE_SECP521R1 = 0x24, /** Allowed identifier for Secp521r1 */ #define CX_CURVE_NISTP521 CX_CURVE_SECP521R1 #endif #ifdef HAVE_BRAINPOOL_P256T1_CURVE - /** BrainpoolP256t1 */ - CX_CURVE_BrainPoolP256T1 = 0x31, + /** BrainpoolP256t1 */ + CX_CURVE_BrainPoolP256T1 = 0x31, #endif #ifdef HAVE_BRAINPOOL_P256R1_CURVE - /** BrainpoolP256r1 */ - CX_CURVE_BrainPoolP256R1 = 0x32, + /** BrainpoolP256r1 */ + CX_CURVE_BrainPoolP256R1 = 0x32, #endif #ifdef HAVE_BRAINPOOL_P320T1_CURVE - /** BrainpoolP320t1 */ - CX_CURVE_BrainPoolP320T1 = 0x33, + /** BrainpoolP320t1 */ + CX_CURVE_BrainPoolP320T1 = 0x33, #endif #ifdef HAVE_BRAINPOOL_P320R1_CURVE - /** BrainpoolP320r1 */ - CX_CURVE_BrainPoolP320R1 = 0x34, + /** BrainpoolP320r1 */ + CX_CURVE_BrainPoolP320R1 = 0x34, #endif #ifdef HAVE_BRAINPOOL_P384T1_CURVE - /** BrainpoolP384t1 */ - CX_CURVE_BrainPoolP384T1 = 0x35, + /** BrainpoolP384t1 */ + CX_CURVE_BrainPoolP384T1 = 0x35, #endif #ifdef HAVE_BRAINPOOL_P384R1_CURVE - /** Brainpool384r1 */ - CX_CURVE_BrainPoolP384R1 = 0x36, + /** Brainpool384r1 */ + CX_CURVE_BrainPoolP384R1 = 0x36, #endif #ifdef HAVE_BRAINPOOL_P512T1_CURVE - /** BrainpoolP512t1 */ - CX_CURVE_BrainPoolP512T1 = 0x37, + /** BrainpoolP512t1 */ + CX_CURVE_BrainPoolP512T1 = 0x37, #endif #ifdef HAVE_BRAINPOOL_P512R1_CURVE - /** BrainpoolP512r1 */ - CX_CURVE_BrainPoolP512R1 = 0x38, + /** BrainpoolP512r1 */ + CX_CURVE_BrainPoolP512R1 = 0x38, #endif #ifdef HAVE_BLS12_381_G1_CURVE - /** BLS12-381 G1 */ - CX_CURVE_BLS12_381_G1 = 0x39, + /** BLS12-381 G1 */ + CX_CURVE_BLS12_381_G1 = 0x39, #endif #ifdef HAVE_FR256V1_CURVE - /** ANSSI FRP256 */ - CX_CURVE_FRP256V1 = 0x41, + /** ANSSI FRP256 */ + CX_CURVE_FRP256V1 = 0x41, #endif #ifdef HAVE_STARK256_CURVE - /** Stark */ - CX_CURVE_Stark256 = 0x51, + /** Stark */ + CX_CURVE_Stark256 = 0x51, #endif - /** High limit (not included) of Weierstrass curve ID */ - CX_CURVE_WEIERSTRASS_END = 0x6F, + /** High limit (not included) of Weierstrass curve ID */ + CX_CURVE_WEIERSTRASS_END = 0x6F, -#endif // HAVE_ECC_WEIERSTRASS +#endif // HAVE_ECC_WEIERSTRASS /* ---------------------------- */ /* --- Type Twisted Edwards --- */ /* ---------------------------- */ #ifdef HAVE_ECC_TWISTED_EDWARDS - /** Low limit (not included) of Twisted Edwards curve ID */ - CX_CURVE_TWISTED_EDWARDS_START = 0x70, + /** Low limit (not included) of Twisted Edwards curve ID */ + CX_CURVE_TWISTED_EDWARDS_START = 0x70, #ifdef HAVE_ED25519_CURVE - /** Ed25519 */ - CX_CURVE_Ed25519 = 0x71, + /** Ed25519 */ + CX_CURVE_Ed25519 = 0x71, #endif #ifdef HAVE_ED25519_CURVE - /** Ed448 */ - CX_CURVE_Ed448 = 0x72, + /** Ed448 */ + CX_CURVE_Ed448 = 0x72, #endif - /** High limit (not included) of Twisted Edwards curve ID */ - CX_CURVE_TWISTED_EDWARDS_END = 0x7F, + /** High limit (not included) of Twisted Edwards curve ID */ + CX_CURVE_TWISTED_EDWARDS_END = 0x7F, -#endif // HAVE_ECC_TWISTED_EDWARDS +#endif // HAVE_ECC_TWISTED_EDWARDS /* ----------------------- */ /* --- Type Montgomery --- */ /* ----------------------- */ #ifdef HAVE_ECC_MONTGOMERY - /** Low limit (not included) of Montgomery curve ID */ - CX_CURVE_MONTGOMERY_START = 0x80, + /** Low limit (not included) of Montgomery curve ID */ + CX_CURVE_MONTGOMERY_START = 0x80, #ifdef HAVE_CV25519_CURVE - /** Curve25519 */ - CX_CURVE_Curve25519 = 0x81, + /** Curve25519 */ + CX_CURVE_Curve25519 = 0x81, #endif #ifdef HAVE_CV448_CURVE - /** Curve448 */ - CX_CURVE_Curve448 = 0x82, + /** Curve448 */ + CX_CURVE_Curve448 = 0x82, #endif - /** High limit (not included) of Montgomery curve ID */ - CX_CURVE_MONTGOMERY_END = 0x8F -#endif // HAVE_ECC_MONTGOMERY + /** High limit (not included) of Montgomery curve ID */ + CX_CURVE_MONTGOMERY_END = 0x8F +#endif // HAVE_ECC_MONTGOMERY }; /** Convenience type. See #cx_curve_e. */ typedef enum cx_curve_e cx_curve_t; /** Returns true if the curve identifier is in the specified range @hideinitializer */ -#define CX_CURVE_RANGE(i,dom) ( ((i)>(CX_CURVE_##dom##_START)) && ((i)<(CX_CURVE_##dom##_END)) ) +#define CX_CURVE_RANGE(i, dom) (((i) > (CX_CURVE_##dom##_START)) && ((i) < (CX_CURVE_##dom##_END))) #ifdef HAVE_ECC_WEIERSTRASS /** Returns true if the curve is a short Weierstrass curve @hideinitializer */ -#define CX_CURVE_IS_WEIERSTRASS(c) (((c) > CX_CURVE_WEIERSTRASS_START) && ((c) < CX_CURVE_WEIERSTRASS_END)) +#define CX_CURVE_IS_WEIERSTRASS(c) \ + (((c) > CX_CURVE_WEIERSTRASS_START) && ((c) < CX_CURVE_WEIERSTRASS_END)) #endif #ifdef HAVE_ECC_TWISTED_EDWARDS /** Returns true if the curve is a twisted Edwards curve @hideinitializer */ -#define CX_CURVE_IS_TWISTED_EDWARDS(c) (((c) > CX_CURVE_TWISTED_EDWARDS_START) && ((c) < CX_CURVE_TWISTED_EDWARDS_END)) +#define CX_CURVE_IS_TWISTED_EDWARDS(c) \ + (((c) > CX_CURVE_TWISTED_EDWARDS_START) && ((c) < CX_CURVE_TWISTED_EDWARDS_END)) #endif #ifdef HAVE_ECC_MONTGOMERY /** Returns true if the curve is a Montgomery curve @hideinitializer */ -#define CX_CURVE_IS_MONTGOMERY(c) (((c) > CX_CURVE_MONTGOMERY_START) && ((c) < CX_CURVE_MONTGOMERY_END)) +#define CX_CURVE_IS_MONTGOMERY(c) \ + (((c) > CX_CURVE_MONTGOMERY_START) && ((c) < CX_CURVE_MONTGOMERY_END)) #endif /** @@ -284,7 +287,8 @@ typedef enum cx_curve_e cx_curve_t; * @arg @c bit_size: Curve size in bits * @arg @c length: Component length in bytes * @arg @c a: a coefficient of the curve equation - * @arg @c b: b (Weierstrass or Montgomery) or d (twisted Edwards) coefficient of the curve equation + * @arg @c b: b (Weierstrass or Montgomery) or d (twisted Edwards) coefficient of the curve + * equation * @arg @c p: Prime specifying the base field * @arg @c Gx: x-coordinate of the base point * @arg @c Gy: y-coordinate of the base point @@ -293,20 +297,19 @@ typedef enum cx_curve_e cx_curve_t; * @arg @c Hn: Second Montgomery constant for the curve order * @arg @c Hp: Second Montgomery constant for the field characteristic p */ -#define CX_CURVE_HEADER \ - cx_curve_t curve; \ - unsigned int bit_size; \ - unsigned int length; \ - const uint8_t *a; \ - const uint8_t *b; \ - const uint8_t *p; \ - const uint8_t *Gx; \ - const uint8_t *Gy; \ - const uint8_t *n; \ - const uint8_t *h; \ - const uint8_t *Hn; \ - const uint8_t *Hp; \ - +#define CX_CURVE_HEADER \ + cx_curve_t curve; \ + unsigned int bit_size; \ + unsigned int length; \ + const uint8_t *a; \ + const uint8_t *b; \ + const uint8_t *p; \ + const uint8_t *Gx; \ + const uint8_t *Gy; \ + const uint8_t *n; \ + const uint8_t *h; \ + const uint8_t *Hn; \ + const uint8_t *Hp; /** * @brief Weierstrass curve defined by **y^3 = x^2 + a*x + b over GF(p)**. @@ -314,7 +317,7 @@ typedef enum cx_curve_e cx_curve_t; * @details See #CX_CURVE_HEADER for the structure members. */ struct cx_curve_weierstrass_s { - CX_CURVE_HEADER + CX_CURVE_HEADER }; /** Convenience type. See #cx_curve_weierstrass_s. */ @@ -326,7 +329,7 @@ typedef struct cx_curve_weierstrass_s cx_curve_weierstrass_t; * @details See #CX_CURVE_HEADER for the structure members. */ struct cx_curve_twisted_edwards_s { - CX_CURVE_HEADER + CX_CURVE_HEADER }; /** Convenience type. See #cx_curve_twisted_edwards_s. */ @@ -338,7 +341,7 @@ typedef struct cx_curve_twisted_edwards_s cx_curve_twisted_edwards_t; * @details See #CX_CURVE_HEADER for the structure members. */ struct cx_curve_montgomery_s { - CX_CURVE_HEADER + CX_CURVE_HEADER }; /** Convenience type. See #cx_curve_montgomery_s. */ @@ -350,22 +353,20 @@ typedef struct cx_curve_montgomery_s cx_curve_montgomery_t; * @details See #CX_CURVE_HEADER for the structure members. */ struct cx_curve_domain_s { - CX_CURVE_HEADER + CX_CURVE_HEADER }; /** Convenience type. See #cx_curve_domain_s. */ typedef struct cx_curve_domain_s cx_curve_domain_t; - - /** * @brief Elliptic curve point. */ struct cx_ec_point_s { cx_curve_t curve; ///< Point's curve - cx_bn_t x; ///< x-coordinate in affine representation - cx_bn_t y; ///< y-coordinate in affine representation - cx_bn_t z; ///< z-coordinate = 1 in affine representation + cx_bn_t x; ///< x-coordinate in affine representation + cx_bn_t y; ///< y-coordinate in affine representation + cx_bn_t z; ///< z-coordinate = 1 in affine representation }; /** Convenience type. See #cx_ec_point_s. */ @@ -376,14 +377,14 @@ typedef struct cx_ec_point_s cx_ecpoint_t; */ enum cx_curve_dom_param_s { - CX_CURVE_PARAM_NONE = 0, ///< No parameter - CX_CURVE_PARAM_A = 1, ///< First coefficient of the curve - CX_CURVE_PARAM_B = 2, ///< Second coefficient of the curve - CX_CURVE_PARAM_Field = 3, ///< Curve field - CX_CURVE_PARAM_Gx = 4, ///< x-coordinate of the curve's generator - CX_CURVE_PARAM_Gy = 5, ///< y-coordinate of the curve's generator - CX_CURVE_PARAM_Order = 6, ///< Order of the generator - CX_CURVE_PARAM_Cofactor = 7, ///< Cofactor + CX_CURVE_PARAM_NONE = 0, ///< No parameter + CX_CURVE_PARAM_A = 1, ///< First coefficient of the curve + CX_CURVE_PARAM_B = 2, ///< Second coefficient of the curve + CX_CURVE_PARAM_Field = 3, ///< Curve field + CX_CURVE_PARAM_Gx = 4, ///< x-coordinate of the curve's generator + CX_CURVE_PARAM_Gy = 5, ///< y-coordinate of the curve's generator + CX_CURVE_PARAM_Order = 6, ///< Order of the generator + CX_CURVE_PARAM_Cofactor = 7, ///< Cofactor }; typedef enum cx_curve_dom_param_s cx_curve_dom_param_t; @@ -430,7 +431,10 @@ SYSCALL cx_err_t cx_ecdomain_parameters_length(cx_curve_t cv, size_t *length); * - CX_EC_INVALID_CURVE * - CX_INVALID_PARAMETER */ -SYSCALL cx_err_t cx_ecdomain_parameter(cx_curve_t cv, cx_curve_dom_param_t id, uint8_t *p PLENGTH(p_len), uint32_t p_len); +SYSCALL cx_err_t cx_ecdomain_parameter(cx_curve_t cv, + cx_curve_dom_param_t id, + uint8_t *p PLENGTH(p_len), + uint32_t p_len); /** * @brief Stores a specific parameter of the curve as a BN. @@ -466,7 +470,10 @@ SYSCALL cx_err_t cx_ecdomain_parameter_bn(cx_curve_t cv, cx_curve_dom_param_t id * - CX_EC_INVALID_CURVE * - CX_INVALID_PARAMETER */ -SYSCALL cx_err_t cx_ecdomain_generator(cx_curve_t cv, uint8_t *Gx PLENGTH(len), uint8_t *Gy PLENGTH(len), size_t len); +SYSCALL cx_err_t cx_ecdomain_generator(cx_curve_t cv, + uint8_t *Gx PLENGTH(len), + uint8_t *Gy PLENGTH(len), + size_t len); /** * @brief Gets the generator of the curve and stores it in the point structure. @@ -483,8 +490,8 @@ SYSCALL cx_err_t cx_ecdomain_generator(cx_curve_t cv, uint8_t *Gx PLENGTH(len), * - CX_INVALID_PARAMETER_SIZE * - CX_EC_INVALID_POINT */ -SYSCALL cx_err_t cx_ecdomain_generator_bn(cx_curve_t cv, cx_ecpoint_t *P PLENGTH(sizeof(cx_ecpoint_t))); - +SYSCALL cx_err_t cx_ecdomain_generator_bn(cx_curve_t cv, + cx_ecpoint_t *P PLENGTH(sizeof(cx_ecpoint_t))); /** * @brief Allocates memory for a point on the curve. @@ -537,7 +544,11 @@ SYSCALL cx_err_t cx_ecpoint_destroy(cx_ecpoint_t *P PLENGTH(sizeof(cx_ecpoint_t) * - CX_INVALID_PARAMETER * - CX_EC_INVALID_CURVE */ -SYSCALL cx_err_t cx_ecpoint_init(cx_ecpoint_t *P PLENGTH(sizeof(cx_ecpoint_t)), const uint8_t *x PLENGTH(x_len), size_t x_len, const uint8_t *y PLENGTH(y_len), size_t y_len); +SYSCALL cx_err_t cx_ecpoint_init(cx_ecpoint_t *P PLENGTH(sizeof(cx_ecpoint_t)), + const uint8_t *x PLENGTH(x_len), + size_t x_len, + const uint8_t *y PLENGTH(y_len), + size_t y_len); /** * @brief Initializes a point on the curve with the BN indexes of the coordinates. @@ -556,7 +567,9 @@ SYSCALL cx_err_t cx_ecpoint_init(cx_ecpoint_t *P PLENGTH(sizeof(cx_ecpoint_t)), * - CX_INVALID_PARAMETER * - CX_EC_INVALID_CURVE */ -SYSCALL cx_err_t cx_ecpoint_init_bn(cx_ecpoint_t *P PLENGTH(sizeof(cx_ecpoint_t)), const cx_bn_t x, const cx_bn_t y); +SYSCALL cx_err_t cx_ecpoint_init_bn(cx_ecpoint_t *P PLENGTH(sizeof(cx_ecpoint_t)), + const cx_bn_t x, + const cx_bn_t y); /** * @brief Exports a point. @@ -583,7 +596,11 @@ SYSCALL cx_err_t cx_ecpoint_init_bn(cx_ecpoint_t *P PLENGTH(sizeof(cx_ecpoint_t) * - CX_EC_INFINITE_POINT * - CX_MEMORY_FULL */ -SYSCALL cx_err_t cx_ecpoint_export(const cx_ecpoint_t *P PLENGTH(sizeof(cx_ecpoint_t)), uint8_t *x PLENGTH(x_len), size_t x_len, uint8_t *y PLENGTH(y_len), size_t y_len); +SYSCALL cx_err_t cx_ecpoint_export(const cx_ecpoint_t *P PLENGTH(sizeof(cx_ecpoint_t)), + uint8_t *x PLENGTH(x_len), + size_t x_len, + uint8_t *y PLENGTH(y_len), + size_t y_len); /** * @brief Exports a point using BN indexes of the coordinates. @@ -602,8 +619,9 @@ SYSCALL cx_err_t cx_ecpoint_export(const cx_ecpoint_t *P PLENGTH(sizeof(cx_ecpoi * - CX_EC_INFINITE_POINT * - CX_MEMORY_FULL */ -SYSCALL cx_err_t cx_ecpoint_export_bn(const cx_ecpoint_t *P PLENGTH(sizeof(cx_ecpoint_t)), cx_bn_t *x PLENGTH(sizeof(cx_bn_t)), cx_bn_t *y PLENGTH(sizeof(cx_bn_t))); - +SYSCALL cx_err_t cx_ecpoint_export_bn(const cx_ecpoint_t *P PLENGTH(sizeof(cx_ecpoint_t)), + cx_bn_t *x PLENGTH(sizeof(cx_bn_t)), + cx_bn_t *y PLENGTH(sizeof(cx_bn_t))); /** * @brief Computes the compressed form of a point. @@ -635,7 +653,10 @@ SYSCALL cx_err_t cx_ecpoint_export_bn(const cx_ecpoint_t *P PLENGTH(sizeof(cx_ec * - CX_EC_INFINITE_POINT * - CX_MEMORY_FULL */ -SYSCALL cx_err_t cx_ecpoint_compress(const cx_ecpoint_t *P PLENGTH(sizeof(cx_ecpoint_t)), uint8_t* xy_compressed PLENGTH(xy_compressed_len), size_t xy_compressed_len, uint32_t *sign); +SYSCALL cx_err_t cx_ecpoint_compress(const cx_ecpoint_t *P PLENGTH(sizeof(cx_ecpoint_t)), + uint8_t *xy_compressed PLENGTH(xy_compressed_len), + size_t xy_compressed_len, + uint32_t *sign); /** * @brief Computes the affine coordinates of a point given its compressed form. @@ -659,7 +680,10 @@ SYSCALL cx_err_t cx_ecpoint_compress(const cx_ecpoint_t *P PLENGTH(sizeof(cx_ecp * - CX_NO_RESIDUE * */ -SYSCALL cx_err_t cx_ecpoint_decompress(cx_ecpoint_t *P PLENGTH(sizeof(cx_ecpoint_t)), const uint8_t* xy_compressed PLENGTH(xy_compressed_len), size_t xy_compressed_len, uint32_t sign); +SYSCALL cx_err_t cx_ecpoint_decompress(cx_ecpoint_t *P PLENGTH(sizeof(cx_ecpoint_t)), + const uint8_t *xy_compressed PLENGTH(xy_compressed_len), + size_t xy_compressed_len, + uint32_t sign); /** * @brief Adds two points on a curve. @@ -685,7 +709,9 @@ SYSCALL cx_err_t cx_ecpoint_decompress(cx_ecpoint_t *P PLENGTH(sizeof(cx_ecpoint * - CX_EC_INFINITE_POINT * - CX_MEMORY_FULL */ -SYSCALL cx_err_t cx_ecpoint_add(cx_ecpoint_t *R PLENGTH(sizeof(cx_ecpoint_t)), const cx_ecpoint_t *P PLENGTH(sizeof(cx_ecpoint_t)), const cx_ecpoint_t *Q PLENGTH(sizeof(cx_ecpoint_t))); +SYSCALL cx_err_t cx_ecpoint_add(cx_ecpoint_t *R PLENGTH(sizeof(cx_ecpoint_t)), + const cx_ecpoint_t *P PLENGTH(sizeof(cx_ecpoint_t)), + const cx_ecpoint_t *Q PLENGTH(sizeof(cx_ecpoint_t))); /** * @brief Computes the opposite of a point. @@ -727,7 +753,9 @@ SYSCALL cx_err_t cx_ecpoint_neg(cx_ecpoint_t *P PLENGTH(sizeof(cx_ecpoint_t))); * - CX_EC_INFINITE_POINT * - CX_MEMORY_FULL */ -SYSCALL cx_err_t cx_ecpoint_rnd_scalarmul(cx_ecpoint_t *P PLENGTH(sizeof(cx_ecpoint_t)), const uint8_t* k PLENGTH(k_len), size_t k_len); +SYSCALL cx_err_t cx_ecpoint_rnd_scalarmul(cx_ecpoint_t *P PLENGTH(sizeof(cx_ecpoint_t)), + const uint8_t *k PLENGTH(k_len), + size_t k_len); /** * @brief Performs a secure scalar multiplication given the BN index of the scalar. @@ -746,7 +774,8 @@ SYSCALL cx_err_t cx_ecpoint_rnd_scalarmul(cx_ecpoint_t *P PLENGTH(sizeof(cx_ecpo * - CX_EC_INFINITE_POINT * - CX_MEMORY_FULL */ -SYSCALL cx_err_t cx_ecpoint_rnd_scalarmul_bn(cx_ecpoint_t *P PLENGTH(sizeof(cx_ecpoint_t)), const cx_bn_t bn_k PLENGTH(sizeof(cx_bn_t))); +SYSCALL cx_err_t cx_ecpoint_rnd_scalarmul_bn(cx_ecpoint_t *P PLENGTH(sizeof(cx_ecpoint_t)), + const cx_bn_t bn_k PLENGTH(sizeof(cx_bn_t))); /** * @brief Performs a secure scalar multiplication with a fixed scalar length. @@ -767,7 +796,9 @@ SYSCALL cx_err_t cx_ecpoint_rnd_scalarmul_bn(cx_ecpoint_t *P PLENGTH(sizeof(cx_e * - CX_EC_INFINITE_POINT * - CX_MEMORY_FULL */ -SYSCALL cx_err_t cx_ecpoint_rnd_fixed_scalarmul(cx_ecpoint_t *P PLENGTH(sizeof(cx_ecpoint_t)), const uint8_t* k PLENGTH(k_len), size_t k_len); +SYSCALL cx_err_t cx_ecpoint_rnd_fixed_scalarmul(cx_ecpoint_t *P PLENGTH(sizeof(cx_ecpoint_t)), + const uint8_t *k PLENGTH(k_len), + size_t k_len); /** * @brief Performs a scalar multiplication. @@ -792,7 +823,9 @@ SYSCALL cx_err_t cx_ecpoint_rnd_fixed_scalarmul(cx_ecpoint_t *P PLENGTH(sizeof(c * - CX_EC_INFINITE_POINT * - CX_MEMORY_FULL */ -SYSCALL cx_err_t cx_ecpoint_scalarmul(cx_ecpoint_t *P PLENGTH(sizeof(cx_ecpoint_t)), const uint8_t* k PLENGTH(k_len), size_t k_len); +SYSCALL cx_err_t cx_ecpoint_scalarmul(cx_ecpoint_t *P PLENGTH(sizeof(cx_ecpoint_t)), + const uint8_t *k PLENGTH(k_len), + size_t k_len); /** * @brief Performs a scalar multiplication given the BN index of the scalar. @@ -815,7 +848,8 @@ SYSCALL cx_err_t cx_ecpoint_scalarmul(cx_ecpoint_t *P PLENGTH(sizeof(cx_ecpoint_ * - CX_EC_INFINITE_POINT * - CX_MEMORY_FULL */ -SYSCALL cx_err_t cx_ecpoint_scalarmul_bn(cx_ecpoint_t *P PLENGTH(sizeof(cx_ecpoint_t)), const cx_bn_t bn_k PLENGTH(sizeof(cx_bn_t))); +SYSCALL cx_err_t cx_ecpoint_scalarmul_bn(cx_ecpoint_t *P PLENGTH(sizeof(cx_ecpoint_t)), + const cx_bn_t bn_k PLENGTH(sizeof(cx_bn_t))); /** * @brief Performs a double scalar multiplication. @@ -846,7 +880,13 @@ SYSCALL cx_err_t cx_ecpoint_scalarmul_bn(cx_ecpoint_t *P PLENGTH(sizeof(cx_ecpoi * - CX_MEMORY_FULL * - CX_EC_INFINITE_POINT */ -SYSCALL cx_err_t cx_ecpoint_double_scalarmul(cx_ecpoint_t *R PLENGTH(sizeof(cx_ecpoint_t)), cx_ecpoint_t *P PLENGTH(sizeof(cx_ecpoint_t)), cx_ecpoint_t *Q PLENGTH(sizeof(cx_ecpoint_t)), const uint8_t *k PLENGTH(k_len), size_t k_len, const uint8_t *r PLENGTH(r_len), size_t r_len); +SYSCALL cx_err_t cx_ecpoint_double_scalarmul(cx_ecpoint_t *R PLENGTH(sizeof(cx_ecpoint_t)), + cx_ecpoint_t *P PLENGTH(sizeof(cx_ecpoint_t)), + cx_ecpoint_t *Q PLENGTH(sizeof(cx_ecpoint_t)), + const uint8_t *k PLENGTH(k_len), + size_t k_len, + const uint8_t *r PLENGTH(r_len), + size_t r_len); /** * @brief Performs a double scalar multiplication @@ -874,7 +914,11 @@ SYSCALL cx_err_t cx_ecpoint_double_scalarmul(cx_ecpoint_t *R PLENGTH(sizeof(cx_e * - CX_MEMORY_FULL * - CX_EC_INFINITE_POINT */ -SYSCALL cx_err_t cx_ecpoint_double_scalarmul_bn(cx_ecpoint_t *R PLENGTH(sizeof(cx_ecpoint_t)), cx_ecpoint_t *P PLENGTH(sizeof(cx_ecpoint_t)), cx_ecpoint_t *Q PLENGTH(sizeof(cx_ecpoint_t)), const cx_bn_t bn_k, const cx_bn_t bn_r); +SYSCALL cx_err_t cx_ecpoint_double_scalarmul_bn(cx_ecpoint_t *R PLENGTH(sizeof(cx_ecpoint_t)), + cx_ecpoint_t *P PLENGTH(sizeof(cx_ecpoint_t)), + cx_ecpoint_t *Q PLENGTH(sizeof(cx_ecpoint_t)), + const cx_bn_t bn_k, + const cx_bn_t bn_r); /** * @brief Compares two points on the same curve. @@ -895,7 +939,9 @@ SYSCALL cx_err_t cx_ecpoint_double_scalarmul_bn(cx_ecpoint_t *R PLENGTH(sizeof(c * - CX_EC_INFINITE_POINT * - CX_MEMORY_FULL */ -SYSCALL cx_err_t cx_ecpoint_cmp(const cx_ecpoint_t *P PLENGTH(sizeof(cx_ecpoint_t)), const cx_ecpoint_t *Q PLENGTH(sizeof(cx_ecpoint_t)), bool *is_equal); +SYSCALL cx_err_t cx_ecpoint_cmp(const cx_ecpoint_t *P PLENGTH(sizeof(cx_ecpoint_t)), + const cx_ecpoint_t *Q PLENGTH(sizeof(cx_ecpoint_t)), + bool *is_equal); /** * @brief Checks whether a given point is on the curve. @@ -914,7 +960,8 @@ SYSCALL cx_err_t cx_ecpoint_cmp(const cx_ecpoint_t *P PLENGTH(sizeof(cx_ecpoint_ * - CX_EC_INFINITE_POINT * - CX_MEMORY_FULL */ -SYSCALL cx_err_t cx_ecpoint_is_on_curve(const cx_ecpoint_t *R PLENGTH(sizeof(cx_ecpoint_t)), bool *is_on_curve); +SYSCALL cx_err_t cx_ecpoint_is_on_curve(const cx_ecpoint_t *R PLENGTH(sizeof(cx_ecpoint_t)), + bool *is_on_curve); /** * @brief Checks whether a given point is the point at infinity. @@ -933,7 +980,8 @@ SYSCALL cx_err_t cx_ecpoint_is_on_curve(const cx_ecpoint_t *R PLENGTH(sizeof(cx_ * - CX_INVALID_PARAMETER * - CX_EC_INVALID_CURVE */ -SYSCALL cx_err_t cx_ecpoint_is_at_infinity(const cx_ecpoint_t *R PLENGTH(sizeof(cx_ecpoint_t)), bool *is_at_infinity); +SYSCALL cx_err_t cx_ecpoint_is_at_infinity(const cx_ecpoint_t *R PLENGTH(sizeof(cx_ecpoint_t)), + bool *is_at_infinity); #ifdef HAVE_X25519 /** @@ -959,7 +1007,7 @@ SYSCALL cx_err_t cx_ecpoint_is_at_infinity(const cx_ecpoint_t *R PLENGTH(sizeof( * */ SYSCALL cx_err_t cx_ecpoint_x25519(const cx_bn_t bn_u, const uint8_t *k, size_t k_len); -#endif // HAVE_X25519 +#endif // HAVE_X25519 #ifdef HAVE_X448 /** @@ -985,6 +1033,6 @@ SYSCALL cx_err_t cx_ecpoint_x25519(const cx_bn_t bn_u, const uint8_t *k, size_t * */ SYSCALL cx_err_t cx_ecpoint_x448(const cx_bn_t bn_u, const uint8_t *k, size_t k_len); -#endif // HAVE_X448 +#endif // HAVE_X448 #endif diff --git a/include/ox_rng.h b/include/ox_rng.h index a21b4d5fa..219c473d8 100644 --- a/include/ox_rng.h +++ b/include/ox_rng.h @@ -1,20 +1,20 @@ /******************************************************************************* -* Ledger Nano S - Secure firmware -* (c) 2022 Ledger -* -* Licensed under the Apache License, Version 2.0 (the "License"); -* you may not use this file except in compliance with the License. -* You may obtain a copy of the License at -* -* http://www.apache.org/licenses/LICENSE-2.0 -* -* Unless required by applicable law or agreed to in writing, software -* distributed under the License is distributed on an "AS IS" BASIS, -* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -* See the License for the specific language governing permissions and -* limitations under the License. -********************************************************************************/ + * Ledger Nano S - Secure firmware + * (c) 2022 Ledger + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + ********************************************************************************/ /** * @file ox_rng.h @@ -38,10 +38,10 @@ * @param[in] size Size of the random data in bytes. * */ -SYSCALL void cx_trng_get_random_data(uint8_t *buf PLENGTH(size), size_t size); +SYSCALL void cx_trng_get_random_data(uint8_t *buf PLENGTH(size), size_t size); -void cx_trng_selftest(void); +void cx_trng_selftest(void); -void cx_trng_init(void); +void cx_trng_init(void); -#endif // OX_RNG_H +#endif // OX_RNG_H diff --git a/include/ox_vss.h b/include/ox_vss.h index d7c4525ef..836f73638 100644 --- a/include/ox_vss.h +++ b/include/ox_vss.h @@ -21,8 +21,8 @@ * */ typedef struct { - uint8_t share[CX_VSS_SECRET_SIZE]; ///< The evaluation of two secret polynomials - uint32_t index; ///< The value to evaluate the polynomials on + uint8_t share[CX_VSS_SECRET_SIZE]; ///< The evaluation of two secret polynomials + uint32_t index; ///< The value to evaluate the polynomials on } cx_vss_share_t; /** @@ -30,7 +30,7 @@ typedef struct { * */ typedef struct { - uint8_t commitment[CX_VSS_SECRET_SIZE]; ///< A point on SECP384R1 which serves as a commitment. + uint8_t commitment[CX_VSS_SECRET_SIZE]; ///< A point on SECP384R1 which serves as a commitment. } cx_vss_commitment_t; /** @@ -40,7 +40,8 @@ typedef struct { * @param[out] commits Pointer to the commitments. * @param[in] point Point on SECP384R1 used to compute the commitments. * @param[in] point_len Length of the point. This must be 2 * 48 bytes. - * @param[in] seed Pointer to a seed used to derive the secret coefficients of the polynomials. + * @param[in] seed Pointer to a seed used to derive the secret coefficients of the + * polynomials. * @param[in] seed_len Length of the seed. * @param[in] secret Pointer to the secret to share. * @param[in] secret_len Length of the secret. This must be less than 48 bytes. @@ -48,16 +49,16 @@ typedef struct { * @param[in] threshold Threshold of the secret sharing. * @return Error code */ -SYSCALL cx_err_t cx_vss_generate_shares(cx_vss_share_t *shares PLENGTH(shares_number), +SYSCALL cx_err_t cx_vss_generate_shares(cx_vss_share_t *shares PLENGTH(shares_number), cx_vss_commitment_t *commits PLENGTH(threshold), - const uint8_t *point, - size_t point_len, - const uint8_t *seed PLENGTH(seed_len), - size_t seed_len, - const uint8_t *secret PLENGTH(secret_len), - size_t secret_len, - uint8_t shares_number, - uint8_t threshold); + const uint8_t *point, + size_t point_len, + const uint8_t *seed PLENGTH(seed_len), + size_t seed_len, + const uint8_t *secret PLENGTH(secret_len), + size_t secret_len, + uint8_t shares_number, + uint8_t threshold); /** * @brief This function combines the given shares to get a secret. @@ -68,10 +69,10 @@ SYSCALL cx_err_t cx_vss_generate_shares(cx_vss_share_t *shares PLENGTH(shares_nu * @param[in] threshold Threshold of the secret sharing. * @return Error code */ -SYSCALL cx_err_t cx_vss_combine_shares(uint8_t *secret PLENGTH(secret_len), - size_t secret_len, +SYSCALL cx_err_t cx_vss_combine_shares(uint8_t *secret PLENGTH(secret_len), + size_t secret_len, cx_vss_share_t *shares PLENGTH(sizeof(cx_vss_share_t)), - uint8_t threshold); + uint8_t threshold); /** * @brief This function verifies whether the coefficients commitments match @@ -86,10 +87,10 @@ SYSCALL cx_err_t cx_vss_combine_shares(uint8_t *secret PLENGTH(secret_len), * @return Error code. */ SYSCALL cx_err_t cx_vss_verify_commits(cx_vss_commitment_t *commitments, - uint8_t threshold, + uint8_t threshold, cx_vss_commitment_t *share_commitment, - uint32_t share_index, - bool *verified); + uint32_t share_index, + bool *verified); -#endif /* OX_VSS_H */ -#endif // HAVE_VSS +#endif /* OX_VSS_H */ +#endif // HAVE_VSS diff --git a/include/seproxyhal_protocol.h b/include/seproxyhal_protocol.h index 20dade09e..e4ffe62c6 100644 --- a/include/seproxyhal_protocol.h +++ b/include/seproxyhal_protocol.h @@ -1,91 +1,99 @@ /******************************************************************************* -* Ledger Nano S - Secure firmware -* (c) 2022 Ledger -* -* Licensed under the Apache License, Version 2.0 (the "License"); -* you may not use this file except in compliance with the License. -* You may obtain a copy of the License at -* -* http://www.apache.org/licenses/LICENSE-2.0 -* -* Unless required by applicable law or agreed to in writing, software -* distributed under the License is distributed on an "AS IS" BASIS, -* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -* See the License for the specific language governing permissions and -* limitations under the License. -********************************************************************************/ + * Ledger Nano S - Secure firmware + * (c) 2022 Ledger + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT 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 SEPROXYHAL_PROTOCOL_H #define SEPROXYHAL_PROTOCOL_H -#define BLE_CMD_APDU 0x05 -#define BLE_CHUNK_LENGTH 20 +#define BLE_CMD_APDU 0x05 +#define BLE_CHUNK_LENGTH 20 #define M24SR_CHUNK_LENGTH 0xF6 // EVENTS -#define SEPROXYHAL_TAG_SESSION_START_EVENT 0x01 // - // - // - // - // - // +#define SEPROXYHAL_TAG_SESSION_START_EVENT \ + 0x01 // + // + // + // + // + // #define SEPROXYHAL_TAG_SESSION_START_EVENT_REQBLE 0x01 #define SEPROXYHAL_TAG_SESSION_START_EVENT_RECOVERY 0x02 #define SEPROXYHAL_TAG_SESSION_START_EVENT_FLASHBACK 0x04 #define SEPROXYHAL_TAG_SESSION_START_EVENT_BOOTMENU 0x08 -#define SEPROXYHAL_TAG_SESSION_START_EVENT_FEATURE_USB 0x00000001UL -#define SEPROXYHAL_TAG_SESSION_START_EVENT_FEATURE_BLE 0x00000002UL -#define SEPROXYHAL_TAG_SESSION_START_EVENT_FEATURE_TOUCH 0x00000004UL -#define SEPROXYHAL_TAG_SESSION_START_EVENT_FEATURE_BUTTON_COUNT 0x000000F0UL +#define SEPROXYHAL_TAG_SESSION_START_EVENT_FEATURE_USB 0x00000001UL +#define SEPROXYHAL_TAG_SESSION_START_EVENT_FEATURE_BLE 0x00000002UL +#define SEPROXYHAL_TAG_SESSION_START_EVENT_FEATURE_TOUCH 0x00000004UL +#define SEPROXYHAL_TAG_SESSION_START_EVENT_FEATURE_BUTTON_COUNT 0x000000F0UL #define SEPROXYHAL_TAG_SESSION_START_EVENT_FEATURE_BUTTON_COUNT_POS 4 -#define SEPROXYHAL_TAG_SESSION_START_EVENT_FEATURE_SCREEN_MASK 0x00000F00UL -#define SEPROXYHAL_TAG_SESSION_START_EVENT_FEATURE_NO_SCREEN 0x00000000UL -#define SEPROXYHAL_TAG_SESSION_START_EVENT_FEATURE_SCREEN_BIG 0x00000100UL -#define SEPROXYHAL_TAG_SESSION_START_EVENT_FEATURE_SCREEN_SML 0x00000200UL -#define SEPROXYHAL_TAG_SESSION_START_EVENT_FEATURE_SCREEN_SSD1312 0x00000300UL -#define SEPROXYHAL_TAG_SESSION_START_EVENT_FEATURE_LEDRGB 0x00001000UL -#define SEPROXYHAL_TAG_SESSION_START_EVENT_FEATURE_BATTERY 0x00000008UL -#define SEPROXYHAL_TAG_SESSION_START_EVENT_FEATURE_ISET_MASK 0xF0000000UL -#define SEPROXYHAL_TAG_SESSION_START_EVENT_FEATURE_ISET_BASIC 0x00000000UL -#define SEPROXYHAL_TAG_SESSION_START_EVENT_FEATURE_ISET_MCUSEC 0x10000000UL -#define SEPROXYHAL_TAG_SESSION_START_EVENT_FEATURE_ISET_MCUBL 0x20000000UL - -#define SEPROXYHAL_TAG_BLE_SECURITY_DB_EVENT 0x02 -#define SEPROXYHAL_TAG_BLE_SECURITY_DB_LOADED_EVENT 0x00 // the security db chunk has ben loaded into MCU's RAM, the SE can proceed with the next one -#define SEPROXYHAL_TAG_BLE_SECURITY_DB_DUMP_EVENT 0x01 // content of the security db at given offset -#define SEPROXYHAL_TAG_BLE_WRITE_REQUEST_EVENT 0x03 -#define SEPROXYHAL_TAG_BLE_READ_REQUEST_EVENT 0x04 -#define SEPROXYHAL_TAG_BUTTON_PUSH_EVENT 0x05 -#define SEPROXYHAL_TAG_BUTTON_PUSH_ID_MASK 0xFE // up to 7 physical buttons (bit is 1 when pressed, and 0 when released) -#define SEPROXYHAL_TAG_BUTTON_PUSH_INTERVAL_MS 100 // an event generated every x ms -#define SEPROXYHAL_TAG_NFC_FIELD_DETECTION_EVENT 0x06 -#define SEPROXYHAL_TAG_NFC_APDU_RECEIVED_EVENT 0x07 -#define SEPROXYHAL_TAG_BATTERY_NOTIFICATION_EVENT 0x08 -#define SEPROXYHAL_TAG_M24SR_GPO_CHANGE_EVENT 0x09 -#define SEPROXYHAL_TAG_M24SR_RESPONSE_APDU_EVENT 0x0A -#define SEPROXYHAL_TAG_BLE_NOTIFY_INDICATE_EVENT 0x0B -#define SEPROXYHAL_TAG_FINGER_EVENT 0x0C -#define SEPROXYHAL_TAG_FINGER_EVENT_TOUCH 0x01 -#define SEPROXYHAL_TAG_FINGER_EVENT_RELEASE 0x02 -#define SEPROXYHAL_TAG_DISPLAY_PROCESSED_EVENT 0x0D -#define SEPROXYHAL_TAG_TICKER_EVENT 0x0E // -#define SEPROXYHAL_TAG_USB_EVENT 0x0F // -#define SEPROXYHAL_TAG_USB_EVENT_RESET 0x01 -#define SEPROXYHAL_TAG_USB_EVENT_SOF 0x02 -#define SEPROXYHAL_TAG_USB_EVENT_SUSPENDED 0x04 -#define SEPROXYHAL_TAG_USB_EVENT_RESUMED 0x08 -#define SEPROXYHAL_TAG_USB_EP_XFER_EVENT 0x10 // -#define SEPROXYHAL_TAG_USB_EP_XFER_SETUP 0x01 -#define SEPROXYHAL_TAG_USB_EP_XFER_IN 0x02 -#define SEPROXYHAL_TAG_USB_EP_XFER_OUT 0x04 -#define SEPROXYHAL_TAG_BLE_CONNECTION_EVENT 0x11 // -#define SEPROXYHAL_TAG_UNSEC_CHUNK_EVENT 0x12 -#define SEPROXYHAL_TAG_ACK_LINK_SPEED 0x13 // -#define SEPROXYHAL_TAG_BLUENRG_RECV_EVENT 0x14 // - -#define SEPROXYHAL_TAG_STATUS_EVENT 0x15 // +#define SEPROXYHAL_TAG_SESSION_START_EVENT_FEATURE_SCREEN_MASK 0x00000F00UL +#define SEPROXYHAL_TAG_SESSION_START_EVENT_FEATURE_NO_SCREEN 0x00000000UL +#define SEPROXYHAL_TAG_SESSION_START_EVENT_FEATURE_SCREEN_BIG 0x00000100UL +#define SEPROXYHAL_TAG_SESSION_START_EVENT_FEATURE_SCREEN_SML 0x00000200UL +#define SEPROXYHAL_TAG_SESSION_START_EVENT_FEATURE_SCREEN_SSD1312 0x00000300UL +#define SEPROXYHAL_TAG_SESSION_START_EVENT_FEATURE_LEDRGB 0x00001000UL +#define SEPROXYHAL_TAG_SESSION_START_EVENT_FEATURE_BATTERY 0x00000008UL +#define SEPROXYHAL_TAG_SESSION_START_EVENT_FEATURE_ISET_MASK 0xF0000000UL +#define SEPROXYHAL_TAG_SESSION_START_EVENT_FEATURE_ISET_BASIC 0x00000000UL +#define SEPROXYHAL_TAG_SESSION_START_EVENT_FEATURE_ISET_MCUSEC 0x10000000UL +#define SEPROXYHAL_TAG_SESSION_START_EVENT_FEATURE_ISET_MCUBL 0x20000000UL + +#define SEPROXYHAL_TAG_BLE_SECURITY_DB_EVENT 0x02 +#define SEPROXYHAL_TAG_BLE_SECURITY_DB_LOADED_EVENT \ + 0x00 // the security db chunk has ben loaded into MCU's RAM, the SE can proceed with the next + // one +#define SEPROXYHAL_TAG_BLE_SECURITY_DB_DUMP_EVENT \ + 0x01 // content of the security db at given offset +#define SEPROXYHAL_TAG_BLE_WRITE_REQUEST_EVENT 0x03 +#define SEPROXYHAL_TAG_BLE_READ_REQUEST_EVENT 0x04 +#define SEPROXYHAL_TAG_BUTTON_PUSH_EVENT 0x05 +#define SEPROXYHAL_TAG_BUTTON_PUSH_ID_MASK \ + 0xFE // up to 7 physical buttons (bit is 1 when pressed, and 0 when released) +#define SEPROXYHAL_TAG_BUTTON_PUSH_INTERVAL_MS 100 // an event generated every x ms +#define SEPROXYHAL_TAG_NFC_FIELD_DETECTION_EVENT 0x06 +#define SEPROXYHAL_TAG_NFC_APDU_RECEIVED_EVENT 0x07 +#define SEPROXYHAL_TAG_BATTERY_NOTIFICATION_EVENT 0x08 +#define SEPROXYHAL_TAG_M24SR_GPO_CHANGE_EVENT 0x09 +#define SEPROXYHAL_TAG_M24SR_RESPONSE_APDU_EVENT 0x0A +#define SEPROXYHAL_TAG_BLE_NOTIFY_INDICATE_EVENT 0x0B +#define SEPROXYHAL_TAG_FINGER_EVENT 0x0C +#define SEPROXYHAL_TAG_FINGER_EVENT_TOUCH 0x01 +#define SEPROXYHAL_TAG_FINGER_EVENT_RELEASE 0x02 +#define SEPROXYHAL_TAG_DISPLAY_PROCESSED_EVENT 0x0D +#define SEPROXYHAL_TAG_TICKER_EVENT 0x0E // +#define SEPROXYHAL_TAG_USB_EVENT 0x0F // +#define SEPROXYHAL_TAG_USB_EVENT_RESET 0x01 +#define SEPROXYHAL_TAG_USB_EVENT_SOF 0x02 +#define SEPROXYHAL_TAG_USB_EVENT_SUSPENDED 0x04 +#define SEPROXYHAL_TAG_USB_EVENT_RESUMED 0x08 +#define SEPROXYHAL_TAG_USB_EP_XFER_EVENT \ + 0x10 // +#define SEPROXYHAL_TAG_USB_EP_XFER_SETUP 0x01 +#define SEPROXYHAL_TAG_USB_EP_XFER_IN 0x02 +#define SEPROXYHAL_TAG_USB_EP_XFER_OUT 0x04 +#define SEPROXYHAL_TAG_BLE_CONNECTION_EVENT 0x11 // +#define SEPROXYHAL_TAG_UNSEC_CHUNK_EVENT 0x12 +#define SEPROXYHAL_TAG_ACK_LINK_SPEED 0x13 // +#define SEPROXYHAL_TAG_BLUENRG_RECV_EVENT 0x14 // + +#define SEPROXYHAL_TAG_STATUS_EVENT \ + 0x15 // + // #define SEPROXYHAL_TAG_STATUS_EVENT_FLAG_CHARGING 0x00000001 #define SEPROXYHAL_TAG_STATUS_EVENT_FLAG_USB_ON 0x00000002 #define SEPROXYHAL_TAG_STATUS_EVENT_FLAG_BLE_ON 0x00000004 @@ -94,134 +102,150 @@ #define SEPROXYHAL_TAG_STATUS_EVENT_FLAG_TEMPERATURE_ISSUE 0x00000020 #define SEPROXYHAL_TAG_STATUS_EVENT_FLAG_BATTERY_ISSUE 0x00000040 -#define SEPROXYHAL_TAG_CAPDU_EVENT 0x16 // raw command apdu transport +#define SEPROXYHAL_TAG_CAPDU_EVENT 0x16 // raw command apdu transport -#define SEPROXYHAL_TAG_I2C_EVENT 0x17 // -#define SEPROXYHAL_TAG_I2C_EVENT_KIND_READ 0x01 -#define SEPROXYHAL_TAG_I2C_EVENT_KIND_WRITE 0x02 -#define SEPROXYHAL_TAG_BLE_RECV_EVENT 0x18 // -#define SEPROXYHAL_TAG_BOOTLOADER_RAPDU_EVENT 0x19 // -#define SEPROXYHAL_TAG_UX_EVENT 0x1A // +#define SEPROXYHAL_TAG_I2C_EVENT 0x17 // +#define SEPROXYHAL_TAG_I2C_EVENT_KIND_READ 0x01 +#define SEPROXYHAL_TAG_I2C_EVENT_KIND_WRITE 0x02 +#define SEPROXYHAL_TAG_BLE_RECV_EVENT 0x18 // +#define SEPROXYHAL_TAG_BOOTLOADER_RAPDU_EVENT 0x19 // +#define SEPROXYHAL_TAG_UX_EVENT 0x1A // #ifdef HAVE_NFC -#define SEPROXYHAL_TAG_NFC_APDU_EVENT 0x1C +#define SEPROXYHAL_TAG_NFC_APDU_EVENT 0x1C #endif -#define SEPH_PROTOCOL_EVT_POWER_BUTTON_EVENT 0x1B +#define SEPH_PROTOCOL_EVT_POWER_BUTTON_EVENT 0x1B #ifdef HAVE_QI_FLASH -#define SEPROXYHAL_TAG_STATUS_EVENT_QI_FLASH_CHECKSUM 0x1D +#define SEPROXYHAL_TAG_STATUS_EVENT_QI_FLASH_CHECKSUM 0x1D #endif // COMMANDS #ifdef HAVE_SEPROXYHAL_MCU -#define SEPROXYHAL_TAG_MCU 0x31 // -#define SEPROXYHAL_TAG_MCU_TYPE_BOOTLOADER 0x00 -#define SEPROXYHAL_TAG_MCU_TYPE_LOCK 0x01 +#define SEPROXYHAL_TAG_MCU 0x31 // +#define SEPROXYHAL_TAG_MCU_TYPE_BOOTLOADER 0x00 +#define SEPROXYHAL_TAG_MCU_TYPE_LOCK 0x01 #ifdef HAVE_MCU_PROTECT -#define SEPROXYHAL_TAG_MCU_TYPE_PROTECT 0x02 // for instance ask RDP2 to be engaged -#endif // HAVE_MCU_PROTECT -#define SEPROXYHAL_TAG_MCU_TYPE_BD_ADDR 0x03 -#define SEPROXYHAL_TAG_MCU_BOOTLOADER SEPROXYHAL_TAG_MCU -#endif // HAVE_SEPROXYHAL_MCU -#define SEPROXYHAL_TAG_UNSEC_CHUNK_READ 0x32 // +#define SEPROXYHAL_TAG_MCU_TYPE_PROTECT 0x02 // for instance ask RDP2 to be engaged +#endif // HAVE_MCU_PROTECT +#define SEPROXYHAL_TAG_MCU_TYPE_BD_ADDR 0x03 +#define SEPROXYHAL_TAG_MCU_BOOTLOADER SEPROXYHAL_TAG_MCU +#endif // HAVE_SEPROXYHAL_MCU +#define SEPROXYHAL_TAG_UNSEC_CHUNK_READ 0x32 // // available if SEPROXYHAL_TAG_SESSION_START_EVENT_FEATURE_ISET_MCUSEC -#define SEPROXYHAL_TAG_UNSEC_CHUNK_READ_EXT 0x33 // -#define SEPROXYHAL_TAG_BLE_SEND 0x38 // -#define SEPROXYHAL_TAG_SET_SCREEN_CONFIG 0x3E // -#define SEPROXYHAL_TAG_SET_LINK_PROP 0x3F // -#define SEPROXYHAL_TAG_BLUENRG_SEND 0x40 // -#define SEPROXYHAL_TAG_BLE_DEFINE_GENERIC_SETTING 0x41 -#define SEPROXYHAL_TAG_BLE_DEFINE_SERVICE_SETTING 0x42 -#define SEPROXYHAL_TAG_NFC_DEFINE_SERVICE_SETTING 0x43 -#define SEPROXYHAL_TAG_BLE_RADIO_POWER 0x44 // +#define SEPROXYHAL_TAG_UNSEC_CHUNK_READ_EXT \ + 0x33 // +#define SEPROXYHAL_TAG_BLE_SEND 0x38 // +#define SEPROXYHAL_TAG_SET_SCREEN_CONFIG \ + 0x3E // +#define SEPROXYHAL_TAG_SET_LINK_PROP 0x3F // +#define SEPROXYHAL_TAG_BLUENRG_SEND 0x40 // +#define SEPROXYHAL_TAG_BLE_DEFINE_GENERIC_SETTING 0x41 +#define SEPROXYHAL_TAG_BLE_DEFINE_SERVICE_SETTING 0x42 +#define SEPROXYHAL_TAG_NFC_DEFINE_SERVICE_SETTING 0x43 +#define SEPROXYHAL_TAG_BLE_RADIO_POWER 0x44 // #define SEPROXYHAL_TAG_BLE_RADIO_POWER_ACTION_ON 0x02 #define SEPROXYHAL_TAG_BLE_RADIO_POWER_ACTION_DBWIPE 0x04 #define SEPROXYHAL_TAG_BLE_RADIO_POWER_FACTORY_TEST 0x40 -#define SEPROXYHAL_TAG_NFC_RADIO_POWER 0x45 -#define SEPROXYHAL_TAG_SE_POWER_OFF 0x46 +#define SEPROXYHAL_TAG_NFC_RADIO_POWER 0x45 +#define SEPROXYHAL_TAG_SE_POWER_OFF 0x46 #ifdef HAVE_NOR_FLASH - #define SEPROXYHAL_TAG_SPI_CS 0x47 +#define SEPROXYHAL_TAG_SPI_CS 0x47 #endif -//#define SEPROXYHAL_TAG_SCREEN_POWER 0x47 -#define SEPROXYHAL_TAG_BLE_SECURITY_DB 0x48 // +// #define SEPROXYHAL_TAG_SCREEN_POWER 0x47 +#define SEPROXYHAL_TAG_BLE_SECURITY_DB 0x48 // // TODO use a pairing key between the SE and MCU to decrypt/encrypt the content of the pairing DB. -#define SEPROXYHAL_TAG_BLE_SECURITY_DB_CMD_READ 0x01 // -noarg- request the content of the security db to be transmitted through SEPROXYHAL_TAG_BLE_SECURITY_DB_EVENT -#define SEPROXYHAL_TAG_BLE_SECURITY_DB_CMD_WRITE 0x02 // request to write a chunk of the security db at the given offset -#define SEPROXYHAL_TAG_BATTERY_CHARGE 0x49 // <> -//#define SEPROXYHAL_TAG_SCREEN_DISPLAY 0x4A // wait for display_event after sent +#define SEPROXYHAL_TAG_BLE_SECURITY_DB_CMD_READ \ + 0x01 // -noarg- request the content of the security db to be transmitted through + // SEPROXYHAL_TAG_BLE_SECURITY_DB_EVENT +#define SEPROXYHAL_TAG_BLE_SECURITY_DB_CMD_WRITE \ + 0x02 // request to write a chunk of the security db at the given offset +#define SEPROXYHAL_TAG_BATTERY_CHARGE 0x49 // <> +// #define SEPROXYHAL_TAG_SCREEN_DISPLAY 0x4A // wait for display_event after sent #ifdef HAVE_NFC -#define SEPROXYHAL_TAG_NFC_RAPDU 0x4A -#define SEPROXYHAL_TAG_NFC_INIT 0x34 +#define SEPROXYHAL_TAG_NFC_RAPDU 0x4A +#define SEPROXYHAL_TAG_NFC_INIT 0x34 #endif -#define SEPROXYHAL_TAG_DEVICE_OFF 0x4B -#define SEPROXYHAL_TAG_MORE_TIME 0x4C -#define SEPROXYHAL_TAG_M24SR_C_APDU 0x4D -#define SEPROXYHAL_TAG_SET_TICKER_INTERVAL 0x4E -#define SEPROXYHAL_TAG_USB_CONFIG 0x4F // -#define SEPROXYHAL_TAG_USB_CONFIG_CONNECT 0x01 // <> -#define SEPROXYHAL_TAG_USB_CONFIG_DISCONNECT 0x02 // <> -#define SEPROXYHAL_TAG_USB_CONFIG_ADDR 0x03 // -#define SEPROXYHAL_TAG_USB_CONFIG_ENDPOINTS 0x04 // [ ] -#define SEPROXYHAL_TAG_USB_CONFIG_TYPE_DISABLED 0x00 -#define SEPROXYHAL_TAG_USB_CONFIG_TYPE_CONTROL 0x01 -#define SEPROXYHAL_TAG_USB_CONFIG_TYPE_INTERRUPT 0x02 -#define SEPROXYHAL_TAG_USB_CONFIG_TYPE_BULK 0x03 -#define SEPROXYHAL_TAG_USB_CONFIG_TYPE_ISOCHRONOUS 0x04 -#define SEPROXYHAL_TAG_USB_EP_PREPARE 0x50 // -#define SEPROXYHAL_TAG_USB_EP_PREPARE_DIR_SETUP 0x10 -#define SEPROXYHAL_TAG_USB_EP_PREPARE_DIR_IN 0x20 -#define SEPROXYHAL_TAG_USB_EP_PREPARE_DIR_OUT 0x30 -#define SEPROXYHAL_TAG_USB_EP_PREPARE_DIR_STALL 0x40 -#define SEPROXYHAL_TAG_USB_EP_PREPARE_DIR_UNSTALL 0x80 -#define SEPROXYHAL_TAG_SET_LED 0x51 // -#define SEPROXYHAL_TAG_REQUEST_STATUS 0x52 // no args, request power levels of all peripherals and current charging state or not if a battery is present. -#define SEPROXYHAL_TAG_RAPDU 0x53 // raw response apdu transport -#define SEPROXYHAL_TAG_I2C_XFER 0x54 // -#define SEPROXYHAL_TAG_UX_CMD 0x5D -#define SEPROXYHAL_TAG_UX_CMD_BLE_DISABLE_ADV 0x00 -#define SEPROXYHAL_TAG_UX_CMD_BLE_ENABLE_ADV 0x01 -#define SEPROXYHAL_TAG_UX_CMD_BLE_RESET_PAIRINGS 0x02 -#define SEPROXYHAL_TAG_UX_CMD_REDISPLAY 0x03 -#define SEPROXYHAL_TAG_UX_CMD_BLE_NAME_CHANGED 0x04 +#define SEPROXYHAL_TAG_DEVICE_OFF 0x4B +#define SEPROXYHAL_TAG_MORE_TIME 0x4C +#define SEPROXYHAL_TAG_M24SR_C_APDU 0x4D +#define SEPROXYHAL_TAG_SET_TICKER_INTERVAL 0x4E +#define SEPROXYHAL_TAG_USB_CONFIG 0x4F // +#define SEPROXYHAL_TAG_USB_CONFIG_CONNECT 0x01 // <> +#define SEPROXYHAL_TAG_USB_CONFIG_DISCONNECT 0x02 // <> +#define SEPROXYHAL_TAG_USB_CONFIG_ADDR 0x03 // +#define SEPROXYHAL_TAG_USB_CONFIG_ENDPOINTS \ + 0x04 // [ + // ] +#define SEPROXYHAL_TAG_USB_CONFIG_TYPE_DISABLED 0x00 +#define SEPROXYHAL_TAG_USB_CONFIG_TYPE_CONTROL 0x01 +#define SEPROXYHAL_TAG_USB_CONFIG_TYPE_INTERRUPT 0x02 +#define SEPROXYHAL_TAG_USB_CONFIG_TYPE_BULK 0x03 +#define SEPROXYHAL_TAG_USB_CONFIG_TYPE_ISOCHRONOUS 0x04 +#define SEPROXYHAL_TAG_USB_EP_PREPARE \ + 0x50 // +#define SEPROXYHAL_TAG_USB_EP_PREPARE_DIR_SETUP 0x10 +#define SEPROXYHAL_TAG_USB_EP_PREPARE_DIR_IN 0x20 +#define SEPROXYHAL_TAG_USB_EP_PREPARE_DIR_OUT 0x30 +#define SEPROXYHAL_TAG_USB_EP_PREPARE_DIR_STALL 0x40 +#define SEPROXYHAL_TAG_USB_EP_PREPARE_DIR_UNSTALL 0x80 +#define SEPROXYHAL_TAG_SET_LED 0x51 // +#define SEPROXYHAL_TAG_REQUEST_STATUS \ + 0x52 // no args, request power levels of all peripherals and current charging state or not if a + // battery is present. +#define SEPROXYHAL_TAG_RAPDU 0x53 // raw response apdu transport +#define SEPROXYHAL_TAG_I2C_XFER \ + 0x54 // +#define SEPROXYHAL_TAG_UX_CMD 0x5D +#define SEPROXYHAL_TAG_UX_CMD_BLE_DISABLE_ADV 0x00 +#define SEPROXYHAL_TAG_UX_CMD_BLE_ENABLE_ADV 0x01 +#define SEPROXYHAL_TAG_UX_CMD_BLE_RESET_PAIRINGS 0x02 +#define SEPROXYHAL_TAG_UX_CMD_REDISPLAY 0x03 +#define SEPROXYHAL_TAG_UX_CMD_BLE_NAME_CHANGED 0x04 #ifdef HAVE_SERIALIZED_NBGL -#define SEPROXYHAL_TAG_NBGL_SERIALIZED 0x5C +#define SEPROXYHAL_TAG_NBGL_SERIALIZED 0x5C #endif -#define SEPROXYHAL_TAG_SET_TOUCH_STATE 0x5B +#define SEPROXYHAL_TAG_SET_TOUCH_STATE 0x5B -#define SEPROXYHAL_TAG_PRINTF 0x5F // -#define SEPROXYHAL_TAG_DBG_SCREEN_DISPLAY_STATUS 0x5E // +#define SEPROXYHAL_TAG_PRINTF 0x5F // +#define SEPROXYHAL_TAG_DBG_SCREEN_DISPLAY_STATUS 0x5E // #ifdef HAVE_PIEZO_SOUND -#define SEPROXYHAL_TAG_PLAY_TUNE 0x56 -#endif // HAVE_PIEZO_SOUND +#define SEPROXYHAL_TAG_PLAY_TUNE 0x56 +#endif // HAVE_PIEZO_SOUND #ifdef HAVE_QI_FLASH -#define SEPROXYHAL_TAG_QI_FLASH 0x58 +#define SEPROXYHAL_TAG_QI_FLASH 0x58 #endif #ifdef HAVE_SHIP_MODE -#define SEPH_PROTOCOL_CMD_SET_SHIP_MODE 0x57 -#endif // HAVE_SHIP_MODE +#define SEPH_PROTOCOL_CMD_SET_SHIP_MODE 0x57 +#endif // HAVE_SHIP_MODE // STATUS #define SEPROXYHAL_TAG_STATUS_MASK 0x60 #define SEPROXYHAL_TAG_GENERAL_STATUS 0x60 #define SEPROXYHAL_TAG_GENERAL_STATUS_LAST_COMMAND 0x0000 -//#define SEPROXYHAL_TAG_GENERAL_STATUS_MORE_COMMAND 0x0001 // it's a status, but it shall be a command instead to avoid perturbating the simple seproxyhal bus logic -//#define SEPROXYHAL_TAG_GENERAL_STATUS_ERROR 0x0002 // shall be a command instead +// #define SEPROXYHAL_TAG_GENERAL_STATUS_MORE_COMMAND 0x0001 // it's a status, but it shall be a +// command instead to avoid perturbating the simple seproxyhal bus logic #define +// SEPROXYHAL_TAG_GENERAL_STATUS_ERROR 0x0002 // shall be a command instead #define SEPROXYHAL_TAG_PAIRING_STATUS 0x61 #define SEPROXYHAL_TAG_BLE_READ_RESPONSE_STATUS 0x62 #define SEPROXYHAL_TAG_NFC_READ_RESPONSE_STATUS 0x63 #define SEPROXYHAL_TAG_BLE_NOTIFY_INDICATE_STATUS 0x64 -#define SEPROXYHAL_TAG_SCREEN_DISPLAY_STATUS 0x65 // +#define SEPROXYHAL_TAG_SCREEN_DISPLAY_STATUS 0x65 // #define SEPROXYHAL_TAG_PRINTF_STATUS 0x66 -#define SEPROXYHAL_TAG_SET_LINK_SPEED 0x67 // -#define SEPROXYHAL_TAG_SCREEN_ANIMATION_STATUS 0x68 // // replied with a display processed event when done -#define SEPROXYHAL_TAG_SCREEN_ANIMATION_STATUS_VERTICAL_SPLIT_SLIDE 0x00 // param[0:1](BE) = split Y coordinate, param[2:3](BE) = animation duration in ms -#define SEPROXYHAL_TAG_BOOTLOADER_CAPDU_STATUS 0x6A // +#define SEPROXYHAL_TAG_SET_LINK_SPEED 0x67 // +#define SEPROXYHAL_TAG_SCREEN_ANIMATION_STATUS \ + 0x68 // // replied with a display processed event when + // done +#define SEPROXYHAL_TAG_SCREEN_ANIMATION_STATUS_VERTICAL_SPLIT_SLIDE \ + 0x00 // param[0:1](BE) = split Y coordinate, param[2:3](BE) = animation duration in ms +#define SEPROXYHAL_TAG_BOOTLOADER_CAPDU_STATUS 0x6A // #endif diff --git a/include/syscalls.h b/include/syscalls.h index 4acdfe872..8ad6c67a3 100644 --- a/include/syscalls.h +++ b/include/syscalls.h @@ -3,319 +3,319 @@ // the number of parameters of a syscall is stored in the syscall id #define SYSCALL_NUMBER_OF_PARAMETERS(id) (((id) >> 24) & 0xf) -#define SYSCALL_get_api_level_ID 0x00000001 -#define SYSCALL_halt_ID 0x00000002 -#define SYSCALL_nvm_write_ID 0x03000003 -#define SYSCALL_nvm_erase_ID 0x02000121 -#define SYSCALL_cx_aes_set_key_hw_ID 0x020000b2 -#define SYSCALL_cx_aes_reset_hw_ID 0x000000b3 -#define SYSCALL_cx_aes_block_hw_ID 0x020000b4 -#define SYSCALL_cx_bn_lock_ID 0x02000112 -#define SYSCALL_cx_bn_unlock_ID 0x000000b6 -#define SYSCALL_cx_bn_is_locked_ID 0x000000b7 -#define SYSCALL_cx_bn_alloc_ID 0x02000113 -#define SYSCALL_cx_bn_alloc_init_ID 0x04000114 -#define SYSCALL_cx_bn_destroy_ID 0x010000bc -#define SYSCALL_cx_bn_nbytes_ID 0x0200010d -#define SYSCALL_cx_bn_init_ID 0x03000115 -#define SYSCALL_cx_bn_rand_ID 0x010000ea -#define SYSCALL_cx_bn_copy_ID 0x020000c0 -#define SYSCALL_cx_bn_set_u32_ID 0x020000c1 -#define SYSCALL_cx_bn_get_u32_ID 0x020000eb -#define SYSCALL_cx_bn_export_ID 0x030000c3 -#define SYSCALL_cx_bn_cmp_ID 0x030000c4 -#define SYSCALL_cx_bn_cmp_u32_ID 0x030000c5 -#define SYSCALL_cx_bn_is_odd_ID 0x02000118 -#define SYSCALL_cx_bn_xor_ID 0x030000c8 -#define SYSCALL_cx_bn_or_ID 0x030000c9 -#define SYSCALL_cx_bn_and_ID 0x030000ca -#define SYSCALL_cx_bn_tst_bit_ID 0x030000cb -#define SYSCALL_cx_bn_set_bit_ID 0x020000cc -#define SYSCALL_cx_bn_clr_bit_ID 0x020000cd -#define SYSCALL_cx_bn_shr_ID 0x020000ce -#define SYSCALL_cx_bn_shl_ID 0x0200011c -#define SYSCALL_cx_bn_cnt_bits_ID 0x020000ec -#define SYSCALL_cx_bn_add_ID 0x03000119 -#define SYSCALL_cx_bn_sub_ID 0x0300011a -#define SYSCALL_cx_bn_mul_ID 0x030000d2 -#define SYSCALL_cx_bn_mod_add_ID 0x040000d3 -#define SYSCALL_cx_bn_mod_sub_ID 0x040000d4 -#define SYSCALL_cx_bn_mod_mul_ID 0x040000d5 -#define SYSCALL_cx_bn_reduce_ID 0x030000d6 -#define SYSCALL_cx_bn_mod_sqrt_ID 0x0400011d -#define SYSCALL_cx_bn_mod_pow_bn_ID 0x040000d7 -#define SYSCALL_cx_bn_mod_pow_ID 0x050000ed -#define SYSCALL_cx_bn_mod_pow2_ID 0x050000ee -#define SYSCALL_cx_bn_mod_invert_nprime_ID 0x030000da -#define SYSCALL_cx_bn_mod_u32_invert_ID 0x03000116 -#define SYSCALL_cx_bn_is_prime_ID 0x020000ef -#define SYSCALL_cx_bn_next_prime_ID 0x010000f0 -#define SYSCALL_cx_bn_rng_ID 0x020001dd -#define SYSCALL_cx_bn_gf2_n_mul_ID 0x05000046 -#define SYSCALL_cx_mont_alloc_ID 0x020000dc -#define SYSCALL_cx_mont_init_ID 0x020000dd -#define SYSCALL_cx_mont_init2_ID 0x030000de -#define SYSCALL_cx_mont_to_montgomery_ID 0x030000df -#define SYSCALL_cx_mont_from_montgomery_ID 0x030000e0 -#define SYSCALL_cx_mont_mul_ID 0x040000e1 -#define SYSCALL_cx_mont_pow_ID 0x050000e2 -#define SYSCALL_cx_mont_pow_bn_ID 0x040000e3 -#define SYSCALL_cx_mont_invert_nprime_ID 0x030000e4 -#define SYSCALL_cx_ecdomain_size_ID 0x0200012e -#define SYSCALL_cx_ecdomain_parameters_length_ID 0x0200012f -#define SYSCALL_cx_ecdomain_parameter_ID 0x04000130 -#define SYSCALL_cx_ecdomain_parameter_bn_ID 0x03000131 -#define SYSCALL_cx_ecdomain_generator_ID 0x04000132 -#define SYSCALL_cx_ecdomain_generator_bn_ID 0x02000133 -#define SYSCALL_cx_ecpoint_alloc_ID 0x020000f1 -#define SYSCALL_cx_ecpoint_destroy_ID 0x010000f2 -#define SYSCALL_cx_ecpoint_init_ID 0x050000f3 -#define SYSCALL_cx_ecpoint_init_bn_ID 0x030000f4 -#define SYSCALL_cx_ecpoint_export_ID 0x050000f5 -#define SYSCALL_cx_ecpoint_export_bn_ID 0x030000f6 -#define SYSCALL_cx_ecpoint_compress_ID 0x0400012c -#define SYSCALL_cx_ecpoint_decompress_ID 0x0400012d -#define SYSCALL_cx_ecpoint_add_ID 0x0300010e -#define SYSCALL_cx_ecpoint_neg_ID 0x0100010f -#define SYSCALL_cx_ecpoint_scalarmul_ID 0x03000110 -#define SYSCALL_cx_ecpoint_scalarmul_bn_ID 0x02000111 -#define SYSCALL_cx_ecpoint_rnd_scalarmul_ID 0x03000127 -#define SYSCALL_cx_ecpoint_rnd_scalarmul_bn_ID 0x02000128 +#define SYSCALL_get_api_level_ID 0x00000001 +#define SYSCALL_halt_ID 0x00000002 +#define SYSCALL_nvm_write_ID 0x03000003 +#define SYSCALL_nvm_erase_ID 0x02000121 +#define SYSCALL_cx_aes_set_key_hw_ID 0x020000b2 +#define SYSCALL_cx_aes_reset_hw_ID 0x000000b3 +#define SYSCALL_cx_aes_block_hw_ID 0x020000b4 +#define SYSCALL_cx_bn_lock_ID 0x02000112 +#define SYSCALL_cx_bn_unlock_ID 0x000000b6 +#define SYSCALL_cx_bn_is_locked_ID 0x000000b7 +#define SYSCALL_cx_bn_alloc_ID 0x02000113 +#define SYSCALL_cx_bn_alloc_init_ID 0x04000114 +#define SYSCALL_cx_bn_destroy_ID 0x010000bc +#define SYSCALL_cx_bn_nbytes_ID 0x0200010d +#define SYSCALL_cx_bn_init_ID 0x03000115 +#define SYSCALL_cx_bn_rand_ID 0x010000ea +#define SYSCALL_cx_bn_copy_ID 0x020000c0 +#define SYSCALL_cx_bn_set_u32_ID 0x020000c1 +#define SYSCALL_cx_bn_get_u32_ID 0x020000eb +#define SYSCALL_cx_bn_export_ID 0x030000c3 +#define SYSCALL_cx_bn_cmp_ID 0x030000c4 +#define SYSCALL_cx_bn_cmp_u32_ID 0x030000c5 +#define SYSCALL_cx_bn_is_odd_ID 0x02000118 +#define SYSCALL_cx_bn_xor_ID 0x030000c8 +#define SYSCALL_cx_bn_or_ID 0x030000c9 +#define SYSCALL_cx_bn_and_ID 0x030000ca +#define SYSCALL_cx_bn_tst_bit_ID 0x030000cb +#define SYSCALL_cx_bn_set_bit_ID 0x020000cc +#define SYSCALL_cx_bn_clr_bit_ID 0x020000cd +#define SYSCALL_cx_bn_shr_ID 0x020000ce +#define SYSCALL_cx_bn_shl_ID 0x0200011c +#define SYSCALL_cx_bn_cnt_bits_ID 0x020000ec +#define SYSCALL_cx_bn_add_ID 0x03000119 +#define SYSCALL_cx_bn_sub_ID 0x0300011a +#define SYSCALL_cx_bn_mul_ID 0x030000d2 +#define SYSCALL_cx_bn_mod_add_ID 0x040000d3 +#define SYSCALL_cx_bn_mod_sub_ID 0x040000d4 +#define SYSCALL_cx_bn_mod_mul_ID 0x040000d5 +#define SYSCALL_cx_bn_reduce_ID 0x030000d6 +#define SYSCALL_cx_bn_mod_sqrt_ID 0x0400011d +#define SYSCALL_cx_bn_mod_pow_bn_ID 0x040000d7 +#define SYSCALL_cx_bn_mod_pow_ID 0x050000ed +#define SYSCALL_cx_bn_mod_pow2_ID 0x050000ee +#define SYSCALL_cx_bn_mod_invert_nprime_ID 0x030000da +#define SYSCALL_cx_bn_mod_u32_invert_ID 0x03000116 +#define SYSCALL_cx_bn_is_prime_ID 0x020000ef +#define SYSCALL_cx_bn_next_prime_ID 0x010000f0 +#define SYSCALL_cx_bn_rng_ID 0x020001dd +#define SYSCALL_cx_bn_gf2_n_mul_ID 0x05000046 +#define SYSCALL_cx_mont_alloc_ID 0x020000dc +#define SYSCALL_cx_mont_init_ID 0x020000dd +#define SYSCALL_cx_mont_init2_ID 0x030000de +#define SYSCALL_cx_mont_to_montgomery_ID 0x030000df +#define SYSCALL_cx_mont_from_montgomery_ID 0x030000e0 +#define SYSCALL_cx_mont_mul_ID 0x040000e1 +#define SYSCALL_cx_mont_pow_ID 0x050000e2 +#define SYSCALL_cx_mont_pow_bn_ID 0x040000e3 +#define SYSCALL_cx_mont_invert_nprime_ID 0x030000e4 +#define SYSCALL_cx_ecdomain_size_ID 0x0200012e +#define SYSCALL_cx_ecdomain_parameters_length_ID 0x0200012f +#define SYSCALL_cx_ecdomain_parameter_ID 0x04000130 +#define SYSCALL_cx_ecdomain_parameter_bn_ID 0x03000131 +#define SYSCALL_cx_ecdomain_generator_ID 0x04000132 +#define SYSCALL_cx_ecdomain_generator_bn_ID 0x02000133 +#define SYSCALL_cx_ecpoint_alloc_ID 0x020000f1 +#define SYSCALL_cx_ecpoint_destroy_ID 0x010000f2 +#define SYSCALL_cx_ecpoint_init_ID 0x050000f3 +#define SYSCALL_cx_ecpoint_init_bn_ID 0x030000f4 +#define SYSCALL_cx_ecpoint_export_ID 0x050000f5 +#define SYSCALL_cx_ecpoint_export_bn_ID 0x030000f6 +#define SYSCALL_cx_ecpoint_compress_ID 0x0400012c +#define SYSCALL_cx_ecpoint_decompress_ID 0x0400012d +#define SYSCALL_cx_ecpoint_add_ID 0x0300010e +#define SYSCALL_cx_ecpoint_neg_ID 0x0100010f +#define SYSCALL_cx_ecpoint_scalarmul_ID 0x03000110 +#define SYSCALL_cx_ecpoint_scalarmul_bn_ID 0x02000111 +#define SYSCALL_cx_ecpoint_rnd_scalarmul_ID 0x03000127 +#define SYSCALL_cx_ecpoint_rnd_scalarmul_bn_ID 0x02000128 #ifdef HAVE_FIXED_SCALAR_LENGTH -#define SYSCALL_cx_ecpoint_rnd_fixed_scalarmul_ID 0x03000129 -#endif // HAVE_FIXED_SCALAR_LENGTH +#define SYSCALL_cx_ecpoint_rnd_fixed_scalarmul_ID 0x03000129 +#endif // HAVE_FIXED_SCALAR_LENGTH -#define SYSCALL_cx_ecpoint_double_scalarmul_ID 0x07000148 -#define SYSCALL_cx_ecpoint_double_scalarmul_bn_ID 0x0500014a -#define SYSCALL_cx_ecpoint_cmp_ID 0x030000fb -#define SYSCALL_cx_ecpoint_is_on_curve_ID 0x020000fc -#define SYSCALL_cx_ecpoint_is_at_infinity_ID 0x0200014b +#define SYSCALL_cx_ecpoint_double_scalarmul_ID 0x07000148 +#define SYSCALL_cx_ecpoint_double_scalarmul_bn_ID 0x0500014a +#define SYSCALL_cx_ecpoint_cmp_ID 0x030000fb +#define SYSCALL_cx_ecpoint_is_on_curve_ID 0x020000fc +#define SYSCALL_cx_ecpoint_is_at_infinity_ID 0x0200014b #ifdef HAVE_X25519 -#define SYSCALL_cx_ecpoint_x25519_ID 0x0300001b -#endif // HAVE_X25519 +#define SYSCALL_cx_ecpoint_x25519_ID 0x0300001b +#endif // HAVE_X25519 #ifdef HAVE_X448 -#define SYSCALL_cx_ecpoint_x448_ID 0x03000060 -#endif // HAVE_X448 +#define SYSCALL_cx_ecpoint_x448_ID 0x03000060 +#endif // HAVE_X448 #ifdef HAVE_VSS -#define SYSCALL_cx_vss_generate_shares_ID 0x0a000001 -#define SYSCALL_cx_vss_combine_shares_ID 0x04000002 -#define SYSCALL_cx_vss_verify_commits_ID 0x05000003 -#endif // HAVE_VSS +#define SYSCALL_cx_vss_generate_shares_ID 0x0a000001 +#define SYSCALL_cx_vss_combine_shares_ID 0x04000002 +#define SYSCALL_cx_vss_verify_commits_ID 0x05000003 +#endif // HAVE_VSS -#define SYSCALL_cx_crc32_hw_ID 0x02000102 +#define SYSCALL_cx_crc32_hw_ID 0x02000102 #ifdef HAVE_BLS -#define SYSCALL_ox_bls12381_sign_ID 0x05000103 -#define SYSCALL_cx_hash_to_field_ID 0x06000104 -#define SYSCALL_cx_bls12381_aggregate_ID 0x05000105 -#define SYSCALL_cx_bls12381_key_gen_ID 0x03000108 -#endif // HAVE_BLS - -#define SYSCALL_cx_get_random_bytes_ID 0x02000107 -#define SYSCALL_cx_trng_get_random_data_ID 0x02000106 - -#define SYSCALL_os_perso_erase_all_ID 0x0000004b -#define SYSCALL_os_perso_set_seed_ID 0x0400004e -#define SYSCALL_os_perso_derive_and_set_seed_ID 0x0700004f -#define SYSCALL_os_perso_set_words_ID 0x02000050 -#define SYSCALL_os_perso_finalize_ID 0x00000051 -#define SYSCALL_os_perso_is_pin_set_ID 0x0000009e -#define SYSCALL_os_perso_isonboarded_ID 0x0000009f -#define SYSCALL_os_perso_setonboardingstatus_ID 0x03000094 -#define SYSCALL_os_perso_derive_node_bip32_ID 0x05000053 -#define SYSCALL_os_perso_derive_node_with_seed_key_ID 0x080000a6 -#define SYSCALL_os_perso_derive_eip2333_ID 0x040000a7 +#define SYSCALL_ox_bls12381_sign_ID 0x05000103 +#define SYSCALL_cx_hash_to_field_ID 0x06000104 +#define SYSCALL_cx_bls12381_aggregate_ID 0x05000105 +#define SYSCALL_cx_bls12381_key_gen_ID 0x03000108 +#endif // HAVE_BLS + +#define SYSCALL_cx_get_random_bytes_ID 0x02000107 +#define SYSCALL_cx_trng_get_random_data_ID 0x02000106 + +#define SYSCALL_os_perso_erase_all_ID 0x0000004b +#define SYSCALL_os_perso_set_seed_ID 0x0400004e +#define SYSCALL_os_perso_derive_and_set_seed_ID 0x0700004f +#define SYSCALL_os_perso_set_words_ID 0x02000050 +#define SYSCALL_os_perso_finalize_ID 0x00000051 +#define SYSCALL_os_perso_is_pin_set_ID 0x0000009e +#define SYSCALL_os_perso_isonboarded_ID 0x0000009f +#define SYSCALL_os_perso_setonboardingstatus_ID 0x03000094 +#define SYSCALL_os_perso_derive_node_bip32_ID 0x05000053 +#define SYSCALL_os_perso_derive_node_with_seed_key_ID 0x080000a6 +#define SYSCALL_os_perso_derive_eip2333_ID 0x040000a7 #ifdef HAVE_RECOVER -#define SYSCALL_os_perso_master_seed_ID 0x02000052 -#define SYSCALL_os_perso_recover_state_ID 0x02000054 -#endif // HAVE_RECOVER +#define SYSCALL_os_perso_master_seed_ID 0x02000052 +#define SYSCALL_os_perso_recover_state_ID 0x02000054 +#endif // HAVE_RECOVER #if defined(HAVE_SEED_COOKIE) -#define SYSCALL_os_perso_seed_cookie_ID 0x010000a8 -#endif // HAVE_SEED_COOKIE - -#define SYSCALL_os_endorsement_get_code_hash_ID 0x01000055 -#define SYSCALL_os_endorsement_get_public_key_ID 0x03000056 -#define SYSCALL_os_endorsement_get_public_key_certificate_ID 0x03000057 -#define SYSCALL_os_endorsement_key1_get_app_secret_ID 0x01000058 -#define SYSCALL_os_endorsement_key1_sign_data_ID 0x03000059 -#define SYSCALL_os_endorsement_key2_derive_sign_data_ID 0x0300005a -#define SYSCALL_os_perso_set_pin_ID 0x0400004c -#define SYSCALL_os_perso_set_current_identity_pin_ID 0x0200004d -#define SYSCALL_os_global_pin_is_validated_ID 0x000000a0 -#define SYSCALL_os_global_pin_check_ID 0x020000a1 -#define SYSCALL_os_global_pin_invalidate_ID 0x0000005d -#define SYSCALL_os_global_pin_retries_ID 0x0000005e -#define SYSCALL_os_registry_count_ID 0x0000005f -#define SYSCALL_os_registry_get_ID 0x02000122 -#define SYSCALL_os_ux_ID 0x01000064 -#define SYSCALL_os_lib_call_ID 0x01000067 -#define SYSCALL_os_lib_end_ID 0x00000068 -#define SYSCALL_os_flags_ID 0x0000006a -#define SYSCALL_os_version_ID 0x0200006b -#define SYSCALL_os_serial_ID 0x0200006c -#define SYSCALL_os_seph_features_ID 0x0000006e -#define SYSCALL_os_seph_version_ID 0x0200006f -#define SYSCALL_os_bootloader_version_ID 0x02000073 -#define SYSCALL_os_factory_setting_get_ID 0x0300014c -#define SYSCALL_os_setting_get_ID 0x03000070 -#define SYSCALL_os_setting_set_ID 0x03000071 -#define SYSCALL_os_get_memory_info_ID 0x01000072 -#define SYSCALL_os_registry_get_tag_ID 0x06000123 -#define SYSCALL_os_registry_get_current_app_tag_ID 0x03000074 -#define SYSCALL_os_registry_delete_app_and_dependees_ID 0x01000124 -#define SYSCALL_os_registry_delete_all_apps_ID 0x00000125 -#define SYSCALL_os_sched_exec_ID 0x01000126 -#define SYSCALL_os_sched_exit_ID 0x0100009a -#define SYSCALL_os_sched_is_running_ID 0x0100009b -#define SYSCALL_os_sched_create_ID 0x0700011b -#define SYSCALL_os_sched_kill_ID 0x01000078 -#define SYSCALL_io_seph_send_ID 0x02000083 -#define SYSCALL_io_seph_is_status_sent_ID 0x00000084 -#define SYSCALL_io_seph_recv_ID 0x03000085 -#define SYSCALL_nvm_write_page_ID 0x0100010a -#define SYSCALL_nvm_erase_page_ID 0x01000136 -#define SYSCALL_try_context_get_ID 0x00000087 -#define SYSCALL_try_context_set_ID 0x0100010b -#define SYSCALL_os_sched_last_status_ID 0x0100009c -#define SYSCALL_os_sched_yield_ID 0x0100009d -#define SYSCALL_os_sched_switch_ID 0x0200009e -#define SYSCALL_os_sched_current_task_ID 0x0000008b -#define SYSCALL_os_allow_protected_flash_ID 0x0000008e -#define SYSCALL_os_deny_protected_flash_ID 0x00000091 -#define SYSCALL_os_allow_protected_ram_ID 0x00000092 -#define SYSCALL_os_deny_protected_ram_ID 0x00000093 +#define SYSCALL_os_perso_seed_cookie_ID 0x010000a8 +#endif // HAVE_SEED_COOKIE + +#define SYSCALL_os_endorsement_get_code_hash_ID 0x01000055 +#define SYSCALL_os_endorsement_get_public_key_ID 0x03000056 +#define SYSCALL_os_endorsement_get_public_key_certificate_ID 0x03000057 +#define SYSCALL_os_endorsement_key1_get_app_secret_ID 0x01000058 +#define SYSCALL_os_endorsement_key1_sign_data_ID 0x03000059 +#define SYSCALL_os_endorsement_key2_derive_sign_data_ID 0x0300005a +#define SYSCALL_os_perso_set_pin_ID 0x0400004c +#define SYSCALL_os_perso_set_current_identity_pin_ID 0x0200004d +#define SYSCALL_os_global_pin_is_validated_ID 0x000000a0 +#define SYSCALL_os_global_pin_check_ID 0x020000a1 +#define SYSCALL_os_global_pin_invalidate_ID 0x0000005d +#define SYSCALL_os_global_pin_retries_ID 0x0000005e +#define SYSCALL_os_registry_count_ID 0x0000005f +#define SYSCALL_os_registry_get_ID 0x02000122 +#define SYSCALL_os_ux_ID 0x01000064 +#define SYSCALL_os_lib_call_ID 0x01000067 +#define SYSCALL_os_lib_end_ID 0x00000068 +#define SYSCALL_os_flags_ID 0x0000006a +#define SYSCALL_os_version_ID 0x0200006b +#define SYSCALL_os_serial_ID 0x0200006c +#define SYSCALL_os_seph_features_ID 0x0000006e +#define SYSCALL_os_seph_version_ID 0x0200006f +#define SYSCALL_os_bootloader_version_ID 0x02000073 +#define SYSCALL_os_factory_setting_get_ID 0x0300014c +#define SYSCALL_os_setting_get_ID 0x03000070 +#define SYSCALL_os_setting_set_ID 0x03000071 +#define SYSCALL_os_get_memory_info_ID 0x01000072 +#define SYSCALL_os_registry_get_tag_ID 0x06000123 +#define SYSCALL_os_registry_get_current_app_tag_ID 0x03000074 +#define SYSCALL_os_registry_delete_app_and_dependees_ID 0x01000124 +#define SYSCALL_os_registry_delete_all_apps_ID 0x00000125 +#define SYSCALL_os_sched_exec_ID 0x01000126 +#define SYSCALL_os_sched_exit_ID 0x0100009a +#define SYSCALL_os_sched_is_running_ID 0x0100009b +#define SYSCALL_os_sched_create_ID 0x0700011b +#define SYSCALL_os_sched_kill_ID 0x01000078 +#define SYSCALL_io_seph_send_ID 0x02000083 +#define SYSCALL_io_seph_is_status_sent_ID 0x00000084 +#define SYSCALL_io_seph_recv_ID 0x03000085 +#define SYSCALL_nvm_write_page_ID 0x0100010a +#define SYSCALL_nvm_erase_page_ID 0x01000136 +#define SYSCALL_try_context_get_ID 0x00000087 +#define SYSCALL_try_context_set_ID 0x0100010b +#define SYSCALL_os_sched_last_status_ID 0x0100009c +#define SYSCALL_os_sched_yield_ID 0x0100009d +#define SYSCALL_os_sched_switch_ID 0x0200009e +#define SYSCALL_os_sched_current_task_ID 0x0000008b +#define SYSCALL_os_allow_protected_flash_ID 0x0000008e +#define SYSCALL_os_deny_protected_flash_ID 0x00000091 +#define SYSCALL_os_allow_protected_ram_ID 0x00000092 +#define SYSCALL_os_deny_protected_ram_ID 0x00000093 #ifdef HAVE_CUSTOM_CA_DETAILS_IN_SETTINGS -#define SYSCALL_os_bolos_custom_ca_get_info_ID 0x01000CA0 -#define SYSCALL_os_bolos_custom_ca_revoke_ID 0x00000CA1 -#endif // HAVE_CUSTOM_CA_DETAILS_IN_SETTINGS +#define SYSCALL_os_bolos_custom_ca_get_info_ID 0x01000CA0 +#define SYSCALL_os_bolos_custom_ca_revoke_ID 0x00000CA1 +#endif // HAVE_CUSTOM_CA_DETAILS_IN_SETTINGS -#define SYSCALL_os_bolos_endorsement_revoke_ID 0x010001ED +#define SYSCALL_os_bolos_endorsement_revoke_ID 0x010001ED #ifndef HAVE_BOLOS_NO_CUSTOMCA -#define SYSCALL_os_customca_verify_ID 0x03000090 -#endif // HAVE_BOLOS_NO_CUSTOMCA +#define SYSCALL_os_customca_verify_ID 0x03000090 +#endif // HAVE_BOLOS_NO_CUSTOMCA #ifdef HAVE_AEM_PIN -#define SYSCALL_os_aem_set_pin_ID 0x02000139 -#define SYSCALL_os_aem_unset_pin_ID 0x0000013a -#define SYSCALL_os_aem_is_pin_set_ID 0x0000013b -#define SYSCALL_os_aem_set_response_ID 0x0300013c -#define SYSCALL_os_aem_activate_response_ID 0x0000013d -#define SYSCALL_os_aem_deactivate_response_ID 0x0000013e -#define SYSCALL_os_aem_is_response_active_ID 0x0000013f -#define SYSCALL_os_aem_is_feature_active_ID 0x00000140 -#define SYSCALL_os_aem_get_response_length_ID 0x00000141 -#define SYSCALL_os_aem_get_response_format_ID 0x00000142 -#define SYSCALL_os_aem_get_response_ID 0x02000143 -#define SYSCALL_os_aem_check_pin_ID 0x02000144 -#define SYSCALL_os_aem_invalidate_pin_ID 0x00000145 -#define SYSCALL_os_aem_get_ptc_ID 0x00000146 -#define SYSCALL_os_aem_is_pin_validated_ID 0x00000147 -#endif // HAVE_AEM_PIN - -#define SYSCALL_os_endorsement_get_metadata_ID 0x02000138 +#define SYSCALL_os_aem_set_pin_ID 0x02000139 +#define SYSCALL_os_aem_unset_pin_ID 0x0000013a +#define SYSCALL_os_aem_is_pin_set_ID 0x0000013b +#define SYSCALL_os_aem_set_response_ID 0x0300013c +#define SYSCALL_os_aem_activate_response_ID 0x0000013d +#define SYSCALL_os_aem_deactivate_response_ID 0x0000013e +#define SYSCALL_os_aem_is_response_active_ID 0x0000013f +#define SYSCALL_os_aem_is_feature_active_ID 0x00000140 +#define SYSCALL_os_aem_get_response_length_ID 0x00000141 +#define SYSCALL_os_aem_get_response_format_ID 0x00000142 +#define SYSCALL_os_aem_get_response_ID 0x02000143 +#define SYSCALL_os_aem_check_pin_ID 0x02000144 +#define SYSCALL_os_aem_invalidate_pin_ID 0x00000145 +#define SYSCALL_os_aem_get_ptc_ID 0x00000146 +#define SYSCALL_os_aem_is_pin_validated_ID 0x00000147 +#endif // HAVE_AEM_PIN + +#define SYSCALL_os_endorsement_get_metadata_ID 0x02000138 #if defined(HAVE_VAULT_RECOVERY_ALGO) -#define SYSCALL_os_perso_derive_and_prepare_seed_ID 0x02000137 -#define SYSCALL_os_perso_derive_and_xor_seed_ID 0x00000149 -#define SYSCALL_os_perso_get_seed_algorithm_ID 0x00000152 -#endif // HAVE_VAULT_RECOVERY_ALGO +#define SYSCALL_os_perso_derive_and_prepare_seed_ID 0x02000137 +#define SYSCALL_os_perso_derive_and_xor_seed_ID 0x00000149 +#define SYSCALL_os_perso_get_seed_algorithm_ID 0x00000152 +#endif // HAVE_VAULT_RECOVERY_ALGO #ifdef HAVE_SE_SCREEN -#define SYSCALL_screen_clear_ID 0x00000079 -#define SYSCALL_screen_update_ID 0x0000007a -#define SYSCALL_screen_set_keepout_ID 0x0400007b +#define SYSCALL_screen_clear_ID 0x00000079 +#define SYSCALL_screen_update_ID 0x0000007a +#define SYSCALL_screen_set_keepout_ID 0x0400007b #ifdef HAVE_BRIGHTNESS_SYSCALL -#define SYSCALL_screen_set_brightness_ID 0x0100008c -#endif // HAVE_BRIGHTNESS_SYSCALL -#define SYSCALL_bagl_hal_draw_bitmap_within_rect_ID 0x0900007c -#define SYSCALL_bagl_hal_draw_rect_ID 0x0500007d +#define SYSCALL_screen_set_brightness_ID 0x0100008c +#endif // HAVE_BRIGHTNESS_SYSCALL +#define SYSCALL_bagl_hal_draw_bitmap_within_rect_ID 0x0900007c +#define SYSCALL_bagl_hal_draw_rect_ID 0x0500007d #endif #ifdef HAVE_BLE -#define SYSCALL_os_ux_set_status_ID_IN 0x02000134 -#define SYSCALL_os_ux_get_status_ID_IN 0x01000135 +#define SYSCALL_os_ux_set_status_ID_IN 0x02000134 +#define SYSCALL_os_ux_get_status_ID_IN 0x01000135 #endif #ifdef HAVE_SE_BUTTON -#define SYSCALL_io_button_read_ID 0x0000008f -#endif // HAVE_SE_BUTTON +#define SYSCALL_io_button_read_ID 0x0000008f +#endif // HAVE_SE_BUTTON -#define SYSCALL_os_standby_ID 0x0000d0d0 +#define SYSCALL_os_standby_ID 0x0000d0d0 #ifdef HAVE_MCU_SERIAL_STORAGE -#define SYSCALL_os_seph_serial_ID 0x0200006d -#endif // HAVE_MCU_SERIAL_STORAGE +#define SYSCALL_os_seph_serial_ID 0x0200006d +#endif // HAVE_MCU_SERIAL_STORAGE #if defined(HAVE_LANGUAGE_PACK) -#define SYSCALL_list_language_packs_ID 0x01000153 -#define SYSCALL_get_language_pack_ID 0x01000154 -#endif //defined(HAVE_LANGUAGE_PACK) +#define SYSCALL_list_language_packs_ID 0x01000153 +#define SYSCALL_get_language_pack_ID 0x01000154 +#endif // defined(HAVE_LANGUAGE_PACK) #ifdef HAVE_IO_I2C -#define SYSCALL_io_i2c_setmode_ID 0x02000095 -#define SYSCALL_io_i2c_prepare_ID 0x01000096 -#define SYSCALL_io_i2c_xfer_ID 0x03000097 +#define SYSCALL_io_i2c_setmode_ID 0x02000095 +#define SYSCALL_io_i2c_prepare_ID 0x01000096 +#define SYSCALL_io_i2c_xfer_ID 0x03000097 #ifndef BOLOS_RELEASE #ifdef BOLOS_DEBUG -#define SYSCALL_io_i2c_dumpstate_ID 0x00000098 -#define SYSCALL_io_debug_ID 0x020000a9 -#endif // BOLOS_DEBUG -#endif // BOLOS_RELEASE -#endif // HAVE_IO_I2C +#define SYSCALL_io_i2c_dumpstate_ID 0x00000098 +#define SYSCALL_io_debug_ID 0x020000a9 +#endif // BOLOS_DEBUG +#endif // BOLOS_RELEASE +#endif // HAVE_IO_I2C #ifdef DEBUG_OS_STACK_CONSUMPTION -#define SYSCALL_os_stack_operations_ID 0x01000199 -#endif // DEBUG_OS_STACK_CONSUMPTION +#define SYSCALL_os_stack_operations_ID 0x01000199 +#endif // DEBUG_OS_STACK_CONSUMPTION #ifdef BOLOS_DEBUG -#define SYSCALL_log_debug_ID 0x0100011e -#define SYSCALL_log_debug_nw_ID 0x0100011f -#define SYSCALL_log_debug_int_ID 0x02000080 -#define SYSCALL_log_debug_int_nw_ID 0x02000081 -#define SYSCALL_log_mem_ID 0x02000120 -#endif // BOLOS_DEBUG +#define SYSCALL_log_debug_ID 0x0100011e +#define SYSCALL_log_debug_nw_ID 0x0100011f +#define SYSCALL_log_debug_int_ID 0x02000080 +#define SYSCALL_log_debug_int_nw_ID 0x02000081 +#define SYSCALL_log_mem_ID 0x02000120 +#endif // BOLOS_DEBUG // Stax syscalls #ifdef HAVE_NBGL -#define SYSCALL_nbgl_front_draw_rect_ID 0x01fa0000 -#define SYSCALL_nbgl_front_draw_horizontal_line_ID 0x03fa0001 -#define SYSCALL_nbgl_front_draw_img_ID 0x04fa0002 -#define SYSCALL_nbgl_front_refresh_area_ID 0x03fa0003 -#define SYSCALL_nbgl_front_draw_img_file_ID 0x05fa0004 -#define SYSCALL_nbgl_side_draw_rect_ID 0x01fa0005 -#define SYSCALL_nbgl_side_draw_horizontal_line_ID 0x03fa0006 -#define SYSCALL_nbgl_side_draw_img_ID 0x04fa0007 -#define SYSCALL_nbgl_side_refresh_area_ID 0x02fa0008 -#define SYSCALL_nbgl_get_font_ID 0x01fa000c -#define SYSCALL_nbgl_screen_reinit_ID 0x00fa000d -#define SYSCALL_nbgl_front_draw_img_rle_ID 0x05fa0010 +#define SYSCALL_nbgl_front_draw_rect_ID 0x01fa0000 +#define SYSCALL_nbgl_front_draw_horizontal_line_ID 0x03fa0001 +#define SYSCALL_nbgl_front_draw_img_ID 0x04fa0002 +#define SYSCALL_nbgl_front_refresh_area_ID 0x03fa0003 +#define SYSCALL_nbgl_front_draw_img_file_ID 0x05fa0004 +#define SYSCALL_nbgl_side_draw_rect_ID 0x01fa0005 +#define SYSCALL_nbgl_side_draw_horizontal_line_ID 0x03fa0006 +#define SYSCALL_nbgl_side_draw_img_ID 0x04fa0007 +#define SYSCALL_nbgl_side_refresh_area_ID 0x02fa0008 +#define SYSCALL_nbgl_get_font_ID 0x01fa000c +#define SYSCALL_nbgl_screen_reinit_ID 0x00fa000d +#define SYSCALL_nbgl_front_draw_img_rle_ID 0x05fa0010 #ifdef HAVE_DISPLAY_FAST_MODE -#define SYSCALL_nbgl_screen_update_temperature_ID 0x01fa0011 -#endif // HAVE_DISPLAY_FAST_MODE +#define SYSCALL_nbgl_screen_update_temperature_ID 0x01fa0011 +#endif // HAVE_DISPLAY_FAST_MODE #ifdef HAVE_CONFIGURABLE_DISPLAY_FAST_MODE -#define SYSCALL_nbgl_screen_config_fast_mode_ID 0x00fa0012 -#endif // HAVE_CONFIGURABLE_DISPLAY_FAST_MODE -#endif // HAVE_NBGL +#define SYSCALL_nbgl_screen_config_fast_mode_ID 0x00fa0012 +#endif // HAVE_CONFIGURABLE_DISPLAY_FAST_MODE +#endif // HAVE_NBGL #ifdef HAVE_BACKGROUND_IMG -#define SYSCALL_fetch_background_img 0x01fa0009 -#define SYSCALL_delete_background_img 0x01fa000a +#define SYSCALL_fetch_background_img 0x01fa0009 +#define SYSCALL_delete_background_img 0x01fa000a #endif #ifdef HAVE_SE_TOUCH -#define SYSCALL_touch_get_last_info_ID 0x01fa000b -#define SYSCALL_touch_exclude_borders_ID 0x01fa000d -#define SYSCALL_touch_set_state_ID 0x01fa000e +#define SYSCALL_touch_get_last_info_ID 0x01fa000b +#define SYSCALL_touch_exclude_borders_ID 0x01fa000d +#define SYSCALL_touch_set_state_ID 0x01fa000e #ifdef HAVE_TOUCH_READ_DEBUG_DATA_SYSCALL -#define SYSCALL_touch_debug_ID 0x02fa000f +#define SYSCALL_touch_debug_ID 0x02fa000f #endif -#endif // HAVE_SE_TOUCH +#endif // HAVE_SE_TOUCH diff --git a/lib_bagl/include/bagl.h b/lib_bagl/include/bagl.h index c582be7c3..d7c94817d 100644 --- a/lib_bagl/include/bagl.h +++ b/lib_bagl/include/bagl.h @@ -1,29 +1,29 @@ /******************************************************************************* -* Ledger Nano S - Secure firmware -* (c) 2022 Ledger -* -* Licensed under the Apache License, Version 2.0 (the "License"); -* you may not use this file except in compliance with the License. -* You may obtain a copy of the License at -* -* http://www.apache.org/licenses/LICENSE-2.0 -* -* Unless required by applicable law or agreed to in writing, software -* distributed under the License is distributed on an "AS IS" BASIS, -* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -* See the License for the specific language governing permissions and -* limitations under the License. -********************************************************************************/ + * Ledger Nano S - Secure firmware + * (c) 2022 Ledger + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT 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 #ifndef BAGL_H_ #define BAGL_H_ -#define BAGL_NOFILL 0 -#define BAGL_FILL 1 +#define BAGL_NOFILL 0 +#define BAGL_FILL 1 #define BAGL_OUTLINE 2 -#define BAGL_NOICON 3 +#define BAGL_NOICON 3 #define BAGL_FILL_CIRCLE_1_OCTANT 1 #define BAGL_FILL_CIRCLE_2_OCTANT 2 @@ -33,11 +33,11 @@ #define BAGL_FILL_CIRCLE_6_OCTANT 32 #define BAGL_FILL_CIRCLE_7_OCTANT 64 #define BAGL_FILL_CIRCLE_8_OCTANT 128 -#define BAGL_FILL_CIRCLE 0xFF -#define BAGL_FILL_CIRCLE_3PI2_2PI (BAGL_FILL_CIRCLE_1_OCTANT|BAGL_FILL_CIRCLE_2_OCTANT) -#define BAGL_FILL_CIRCLE_PI_3PI2 (BAGL_FILL_CIRCLE_3_OCTANT|BAGL_FILL_CIRCLE_4_OCTANT) -#define BAGL_FILL_CIRCLE_0_PI2 (BAGL_FILL_CIRCLE_5_OCTANT|BAGL_FILL_CIRCLE_6_OCTANT) -#define BAGL_FILL_CIRCLE_PI2_PI (BAGL_FILL_CIRCLE_7_OCTANT|BAGL_FILL_CIRCLE_8_OCTANT) +#define BAGL_FILL_CIRCLE 0xFF +#define BAGL_FILL_CIRCLE_3PI2_2PI (BAGL_FILL_CIRCLE_1_OCTANT | BAGL_FILL_CIRCLE_2_OCTANT) +#define BAGL_FILL_CIRCLE_PI_3PI2 (BAGL_FILL_CIRCLE_3_OCTANT | BAGL_FILL_CIRCLE_4_OCTANT) +#define BAGL_FILL_CIRCLE_0_PI2 (BAGL_FILL_CIRCLE_5_OCTANT | BAGL_FILL_CIRCLE_6_OCTANT) +#define BAGL_FILL_CIRCLE_PI2_PI (BAGL_FILL_CIRCLE_7_OCTANT | BAGL_FILL_CIRCLE_8_OCTANT) // Height & Baseline of regular & extrabold 11 px fonts (non unicode characters) // (includes the 3 skipped lines - still for non unicode characters) @@ -47,290 +47,317 @@ // -------------------------------------------------------------------------------------- typedef enum bagl_components_type_e_ { - BAGL_NONE = 0, // for fast memset clearing all components - BAGL_BUTTON = 1, - //BAGL_TEXTBOX, // NOT NECESSARY - //BAGL_SENSEZONE, // sense only - BAGL_LABEL, - BAGL_RECTANGLE, - BAGL_LINE, - BAGL_ICON, - BAGL_CIRCLE, - BAGL_LABELINE, // label for which y coordinate is the baseline of the text, does not support vertical alignment + BAGL_NONE = 0, // for fast memset clearing all components + BAGL_BUTTON = 1, + // BAGL_TEXTBOX, // NOT NECESSARY + // BAGL_SENSEZONE, // sense only + BAGL_LABEL, + BAGL_RECTANGLE, + BAGL_LINE, + BAGL_ICON, + BAGL_CIRCLE, + BAGL_LABELINE, // label for which y coordinate is the baseline of the text, does not support + // vertical alignment #if defined(HAVE_INDEXED_STRINGS) - BAGL_LABELINE_LOC, // Used to store index of string instead of a char *text. -#endif //defined(HAVE_INDEXED_STRINGS) + BAGL_LABELINE_LOC, // Used to store index of string instead of a char *text. +#endif // defined(HAVE_INDEXED_STRINGS) - BAGL_FLAG_TOUCHABLE = 0x80, + BAGL_FLAG_TOUCHABLE = 0x80, } bagl_components_type_e; #define BAGL_TYPE_FLAGS_MASK 0x80 // -------------------------------------------------------------------------------------- typedef struct { - bagl_components_type_e type; - unsigned char userid; - short x; // allow for out of screen rendering - short y; // allow for out of screen rendering - unsigned short width; - unsigned short height; - unsigned char stroke; - unsigned char radius; - unsigned char fill; - unsigned int fgcolor; - unsigned int bgcolor; - unsigned short font_id; - unsigned char icon_id; + bagl_components_type_e type; + unsigned char userid; + short x; // allow for out of screen rendering + short y; // allow for out of screen rendering + unsigned short width; + unsigned short height; + unsigned char stroke; + unsigned char radius; + unsigned char fill; + unsigned int fgcolor; + unsigned int bgcolor; + unsigned short font_id; + unsigned char icon_id; } bagl_component_t; -#define BAGL_FONT_ID_MASK 0x0FFF +#define BAGL_FONT_ID_MASK 0x0FFF #define BAGL_FONT_ALIGNMENT_HORIZONTAL_MASK 0xC000 #define BAGL_FONT_ALIGNMENT_LEFT 0x0000 #define BAGL_FONT_ALIGNMENT_RIGHT 0x4000 #define BAGL_FONT_ALIGNMENT_CENTER 0x8000 -#define BAGL_FONT_ALIGNMENT_VERTICAL_MASK 0x3000 -#define BAGL_FONT_ALIGNMENT_TOP 0x0000 -#define BAGL_FONT_ALIGNMENT_BOTTOM 0x1000 -#define BAGL_FONT_ALIGNMENT_MIDDLE 0x2000 +#define BAGL_FONT_ALIGNMENT_VERTICAL_MASK 0x3000 +#define BAGL_FONT_ALIGNMENT_TOP 0x0000 +#define BAGL_FONT_ALIGNMENT_BOTTOM 0x1000 +#define BAGL_FONT_ALIGNMENT_MIDDLE 0x2000 #define BAGL_STROKE_FLAG_ONESHOT 0x80 // avgcharwidth: the average character width in pixel // stroke: contains the hold time at start and at end (flag oneshot + in x 100ms) // iconid: contains the horizontal scroll speed (in pixel/second) -#define BAGL_LONGLABEL_TIME_MS(textlength,avgcharwidth,stroke,iconid) (2*(textlength*avgcharwidth)*1000/(iconid) + 2*(stroke & ~(BAGL_STROKE_FLAG_ONESHOT) )*100 ) +#define BAGL_LONGLABEL_TIME_MS(textlength, avgcharwidth, stroke, iconid) \ + (2 * (textlength * avgcharwidth) * 1000 / (iconid) \ + + 2 * (stroke & ~(BAGL_STROKE_FLAG_ONESHOT)) * 100) // -------------------------------------------------------------------------------------- - /** * helper structure to help handling icons */ typedef struct bagl_icon_details_s { - unsigned int width; - unsigned int height; - // bit per pixel - unsigned int bpp; - const unsigned int* colors; - const unsigned char* bitmap; + unsigned int width; + unsigned int height; + // bit per pixel + unsigned int bpp; + const unsigned int *colors; + const unsigned char *bitmap; } bagl_icon_details_t; - // -------------------------------------------------------------------------------------- #ifdef HAVE_BAGL_GLYPH_ARRAY typedef struct { - unsigned int icon_id; - unsigned int width; - unsigned int height; - unsigned int bits_per_pixel; - const unsigned int* default_colors; // color array entry count is (1< #include @@ -7,59 +7,59 @@ #include "bagl.h" typedef enum anim_type_e { - /** - * [ label ] << - * [ label ] << - * [label ] << - * [abel ] << - * [bel ] pause - * [abel ] >> - * [label ] >> - * [ label ] >> - * [ label ] >> - * [ label ] >> - * [ label] >> - * [ labe] >> - * [ abe] pause - * [ labe] << - * ... - */ - ANIMATION_TYPE_CLASSIC, - - /** - * [ label ] << - * [ label ] << - * [label ] << - * [abel l] << - * [bel la] << - * [el lab] << - * [l labe] << - * [ label] << - * ... - */ - ANIMATION_TYPE_CIRCLE_RL, - - /** - * [ label ] >> - * [ label ] >> - * [ label] >> - * [l labe] >> - * [el lab] >> - * [bel la] >> - * [abel l] >> - * [label ] >> - * ... - */ - ANIMATION_TYPE_CIRCLE_LR, - - ANIMATION_TYPE_END, + /** + * [ label ] << + * [ label ] << + * [label ] << + * [abel ] << + * [bel ] pause + * [abel ] >> + * [label ] >> + * [ label ] >> + * [ label ] >> + * [ label ] >> + * [ label] >> + * [ labe] >> + * [ abe] pause + * [ labe] << + * ... + */ + ANIMATION_TYPE_CLASSIC, + + /** + * [ label ] << + * [ label ] << + * [label ] << + * [abel l] << + * [bel la] << + * [el lab] << + * [l labe] << + * [ label] << + * ... + */ + ANIMATION_TYPE_CIRCLE_RL, + + /** + * [ label ] >> + * [ label ] >> + * [ label] >> + * [l labe] >> + * [el lab] >> + * [bel la] >> + * [abel l] >> + * [label ] >> + * ... + */ + ANIMATION_TYPE_CIRCLE_LR, + + ANIMATION_TYPE_END, } anim_type_t; typedef enum anim_speed_e { - ANIMATION_SPEED_FAST, // 10ms between two refreshes - ANIMATION_SPEED_NORMAL, // 30ms between two refreshes - ANIMATION_SPEED_SLOW, // 60ms between two refreshes - ANIMATION_SPEED_END + ANIMATION_SPEED_FAST, // 10ms between two refreshes + ANIMATION_SPEED_NORMAL, // 30ms between two refreshes + ANIMATION_SPEED_SLOW, // 60ms between two refreshes + ANIMATION_SPEED_END } anim_speed_t; // Maximum size of the label can be animated @@ -69,35 +69,34 @@ typedef enum anim_speed_e { * Structured used to animate a label. */ typedef struct bagl_anim_s { - anim_type_t type; - - /* Label to animate */ - char label[MAX_LABEL_SIZE]; - size_t len; - - /* Has to be set once at initialization */ - uint16_t tot_w; /* total width of the label in pixel */ - uint16_t max_char_w; /* maximum char width based on "W" in pixel */ - uint16_t reset_cur_x; - uint16_t reset_cur_char_idx; - - /* Current properties of the label to display */ - uint16_t rem_w; /* remaining width to display in pixel */ - uint16_t cur_char_idx; /* index of the current char of the label */ - uint16_t cur_char_w; /* size in pixel of the current char */ - uint16_t cur_char_displayed_w; /* size in pixel displayed of the current char */ - uint16_t cur_x; /* current x position on the screen */ - - union { - struct { - uint8_t state; - uint8_t nr_ticker_pause; - } classic; - struct { - uint16_t char_idx_limit; - } circle; - - }; + anim_type_t type; + + /* Label to animate */ + char label[MAX_LABEL_SIZE]; + size_t len; + + /* Has to be set once at initialization */ + uint16_t tot_w; /* total width of the label in pixel */ + uint16_t max_char_w; /* maximum char width based on "W" in pixel */ + uint16_t reset_cur_x; + uint16_t reset_cur_char_idx; + + /* Current properties of the label to display */ + uint16_t rem_w; /* remaining width to display in pixel */ + uint16_t cur_char_idx; /* index of the current char of the label */ + uint16_t cur_char_w; /* size in pixel of the current char */ + uint16_t cur_char_displayed_w; /* size in pixel displayed of the current char */ + uint16_t cur_x; /* current x position on the screen */ + + union { + struct { + uint8_t state; + uint8_t nr_ticker_pause; + } classic; + struct { + uint16_t char_idx_limit; + } circle; + }; } bagl_anim_t; #ifdef HAVE_SE_SCREEN @@ -105,10 +104,10 @@ typedef struct bagl_anim_s { /** * Initialize a label animation. */ -void bagl_animation_init(bagl_anim_t *anim, - anim_type_t type, +void bagl_animation_init(bagl_anim_t *anim, + anim_type_t type, const unsigned char *label, - size_t len); + size_t len); /** * Has to be called for each step of the animation. diff --git a/lib_bagl/src/bagl.c b/lib_bagl/src/bagl.c index eaf7dd646..758b1eb73 100644 --- a/lib_bagl/src/bagl.c +++ b/lib_bagl/src/bagl.c @@ -1,26 +1,26 @@ /******************************************************************************* -* Ledger Nano S - Secure firmware -* (c) 2022 Ledger -* -* Licensed under the Apache License, Version 2.0 (the "License"); -* you may not use this file except in compliance with the License. -* You may obtain a copy of the License at -* -* http://www.apache.org/licenses/LICENSE-2.0 -* -* Unless required by applicable law or agreed to in writing, software -* distributed under the License is distributed on an "AS IS" BASIS, -* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -* See the License for the specific language governing permissions and -* limitations under the License. -********************************************************************************/ + * Ledger Nano S - Secure firmware + * (c) 2022 Ledger + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + ********************************************************************************/ #ifdef HAVE_BAGL #ifdef DISPLAY_FLOWS #undef HAVE_BOLOS -#define PIC(a) (a) -#endif //DISPLAY_FLOWS +#define PIC(a) (a) +#endif // DISPLAY_FLOWS #include "bagl.h" #include @@ -29,7 +29,7 @@ #include "os.h" #if defined(HAVE_LANGUAGE_PACK) #include "ux.h" -#endif //defined(HAVE_LANGUAGE_PACK) +#endif // defined(HAVE_LANGUAGE_PACK) /** Coordinate system for BAGL: @@ -45,7 +45,6 @@ Y axis | ##### ##### */ - // -------------------------------------------------------------------------------------- // Checks // -------------------------------------------------------------------------------------- @@ -58,11 +57,11 @@ Y axis | ##### #ifndef BAGL_WIDTH #error BAGL_WIDTH not set -#endif // !BAGL_WIDTH +#endif // !BAGL_WIDTH #ifndef BAGL_HEIGHT #error BAGL_HEIGHT not set -#endif // !BAGL_HEIGHT +#endif // !BAGL_HEIGHT // -------------------------------------------------------------------------------------- // Definitions @@ -70,40 +69,40 @@ Y axis | ##### #define ICON_WIDTH 0 #ifndef MIN -#define MIN(x,y) ((x)<(y)?(x):(y)) +#define MIN(x, y) ((x) < (y) ? (x) : (y)) #endif #ifndef MAX -#define MAX(x,y) ((x)>(y)?(x):(y)) +#define MAX(x, y) ((x) > (y) ? (x) : (y)) #endif #ifndef U2BE -#define U2BE(buf, off) ((((buf)[off]&0xFF)<<8) | ((buf)[off+1]&0xFF) ) +#define U2BE(buf, off) ((((buf)[off] & 0xFF) << 8) | ((buf)[off + 1] & 0xFF)) #endif #ifndef U4BE -#define U4BE(buf, off) ((U2BE(buf, off)<<16) | (U2BE(buf, off+2)&0xFFFF)) +#define U4BE(buf, off) ((U2BE(buf, off) << 16) | (U2BE(buf, off + 2) & 0xFFFF)) #endif - // 'Magic' number for x & y to mutualise code from bagl_draw_string -#define MAGIC_XY 12345 +// 'Magic' number for x & y to mutualise code from bagl_draw_string +#define MAGIC_XY 12345 // -------------------------------------------------------------------------------------- // Variables // -------------------------------------------------------------------------------------- #ifdef HAVE_BAGL_GLYPH_ARRAY -const bagl_glyph_array_entry_t* G_glyph_array; +const bagl_glyph_array_entry_t *G_glyph_array; unsigned int G_glyph_count; -#endif // HAVE_BAGL_GLYPH_ARRAY +#endif // HAVE_BAGL_GLYPH_ARRAY #if defined(HAVE_UNICODE_SUPPORT) static const bagl_font_unicode_t *font_unicode; -static unsigned int unicode_byte_count; -#endif //defined(HAVE_UNICODE_SUPPORT) +static unsigned int unicode_byte_count; +#endif // defined(HAVE_UNICODE_SUPPORT) #if defined(HAVE_LANGUAGE_PACK) static const bagl_font_unicode_character_t *unicode_characters; -static const unsigned char *unicode_bitmap; -extern const LANGUAGE_PACK *language_pack; -#endif //defined(HAVE_LANGUAGE_PACK) +static const unsigned char *unicode_bitmap; +extern const LANGUAGE_PACK *language_pack; +#endif // defined(HAVE_LANGUAGE_PACK) // -------------------------------------------------------------------------------------- // API @@ -112,1009 +111,1135 @@ extern const LANGUAGE_PACK *language_pack; void screen_update(void); // -------------------------------------------------------------------------------------- -void bagl_draw_bg(unsigned int color) { - bagl_component_t c; - memset(&c, 0, sizeof(c)); - c.type = BAGL_RECTANGLE; - c.userid = BAGL_NONE; - c.fgcolor = color; - c.x = 0; - c.y = 0; - c.width = BAGL_WIDTH; - c.height = BAGL_HEIGHT; - c.fill = BAGL_FILL; - // draw the rect - bagl_draw_with_context(&c, NULL, 0, 0); +void bagl_draw_bg(unsigned int color) +{ + bagl_component_t c; + memset(&c, 0, sizeof(c)); + c.type = BAGL_RECTANGLE; + c.userid = BAGL_NONE; + c.fgcolor = color; + c.x = 0; + c.y = 0; + c.width = BAGL_WIDTH; + c.height = BAGL_HEIGHT; + c.fill = BAGL_FILL; + // draw the rect + bagl_draw_with_context(&c, NULL, 0, 0); } #ifdef HAVE_BAGL_GLYPH_ARRAY // -------------------------------------------------------------------------------------- // internal helper, get the glyph entry from the glyph id (sparse glyph array support) -const bagl_glyph_array_entry_t* bagl_get_glyph(unsigned int icon_id, const bagl_glyph_array_entry_t* glyph_array, unsigned int glyph_count) { - unsigned int i=glyph_count; +const bagl_glyph_array_entry_t *bagl_get_glyph(unsigned int icon_id, + const bagl_glyph_array_entry_t *glyph_array, + unsigned int glyph_count) +{ + unsigned int i = glyph_count; - while(i--) { - // font id match this entry (non linear) - if (glyph_array[i].icon_id == icon_id) { - return &glyph_array[i]; + while (i--) { + // font id match this entry (non linear) + if (glyph_array[i].icon_id == icon_id) { + return &glyph_array[i]; + } } - } - // id not found - return NULL; + // id not found + return NULL; } -#endif // HAVE_BAGL_GLYPH_ARRAY +#endif // HAVE_BAGL_GLYPH_ARRAY // -------------------------------------------------------------------------------------- // internal helper, get the font entry from the font id (sparse font array support) -const bagl_font_t* bagl_get_font(unsigned int font_id) { - unsigned int i=C_bagl_fonts_count; - font_id &= BAGL_FONT_ID_MASK; - - while(i--) { - // font id match this entry (non indexed array) - if (PIC_FONT(C_bagl_fonts[i])->font_id == font_id) { - return PIC_FONT(C_bagl_fonts[i]); +const bagl_font_t *bagl_get_font(unsigned int font_id) +{ + unsigned int i = C_bagl_fonts_count; + font_id &= BAGL_FONT_ID_MASK; + + while (i--) { + // font id match this entry (non indexed array) + if (PIC_FONT(C_bagl_fonts[i])->font_id == font_id) { + return PIC_FONT(C_bagl_fonts[i]); + } } - } - // id not found - return NULL; + // id not found + return NULL; } #if defined(HAVE_UNICODE_SUPPORT) // ---------------------------------------------------------------------------- // Get the font entry from the font id (sparse font array support) -const bagl_font_unicode_t* bagl_get_font_unicode(unsigned int font_id) { - // Be sure we need to change font - if (font_unicode && PIC_FONTU(font_unicode)->font_id == font_id) { - return font_unicode; - } +const bagl_font_unicode_t *bagl_get_font_unicode(unsigned int font_id) +{ + // Be sure we need to change font + if (font_unicode && PIC_FONTU(font_unicode)->font_id == font_id) { + return font_unicode; + } #if defined(HAVE_LANGUAGE_PACK) - const uint8_t *ptr = (const uint8_t *)language_pack; - const bagl_font_unicode_t *font = (const void *)(PIC(ptr + PIC_LANGU(language_pack)->fonts_offset)); - unicode_characters = PIC_CHARU(ptr + PIC_LANGU(language_pack)->characters_offset); - unicode_bitmap = (const void *)(PIC(ptr + PIC_LANGU(language_pack)->bitmaps_offset)); - - font_id &= BAGL_FONT_ID_MASK; + const uint8_t *ptr = (const uint8_t *) language_pack; + const bagl_font_unicode_t *font + = (const void *) (PIC(ptr + PIC_LANGU(language_pack)->fonts_offset)); + unicode_characters = PIC_CHARU(ptr + PIC_LANGU(language_pack)->characters_offset); + unicode_bitmap = (const void *) (PIC(ptr + PIC_LANGU(language_pack)->bitmaps_offset)); + + font_id &= BAGL_FONT_ID_MASK; + + for (unsigned int i = 0; i < PIC_LANGU(language_pack)->nb_fonts; i++) { + if (PIC_FONTU(font)->font_id == font_id) { + // Update all other global variables + return PIC_FONTU(font); + } + // Compute next Bitmap offset + unicode_bitmap += PIC_FONTU(font)->bitmap_len; - for (unsigned int i=0; i < PIC_LANGU(language_pack)->nb_fonts; i++) { - if (PIC_FONTU(font)->font_id == font_id) { - // Update all other global variables - return PIC_FONTU(font); + // Update all pointers for next font + unicode_characters += PIC_LANGU(language_pack)->nb_characters; + ++font; } - // Compute next Bitmap offset - unicode_bitmap += PIC_FONTU(font)->bitmap_len; - - // Update all pointers for next font - unicode_characters += PIC_LANGU(language_pack)->nb_characters; - ++font; - } -#else //defined(HAVE_LANGUAGE_PACK) - font_id &= BAGL_FONT_ID_MASK; - - for (unsigned int i=0; i < C_bagl_fonts_count; i++) { - if (PIC_FONTU(C_bagl_fonts_unicode[i])->font_id == font_id) { - // Update all other global variables - return PIC_FONTU(C_bagl_fonts_unicode[i]); +#else // defined(HAVE_LANGUAGE_PACK) + font_id &= BAGL_FONT_ID_MASK; + + for (unsigned int i = 0; i < C_bagl_fonts_count; i++) { + if (PIC_FONTU(C_bagl_fonts_unicode[i])->font_id == font_id) { + // Update all other global variables + return PIC_FONTU(C_bagl_fonts_unicode[i]); + } } - } -#endif //defined(HAVE_LANGUAGE_PACK) - // id not found - return NULL; +#endif // defined(HAVE_LANGUAGE_PACK) + // id not found + return NULL; } // ---------------------------------------------------------------------------- -const bagl_font_unicode_character_t *get_unicode_character(unsigned int unicode) { +const bagl_font_unicode_character_t *get_unicode_character(unsigned int unicode) +{ #if defined(HAVE_LANGUAGE_PACK) - const bagl_font_unicode_character_t *characters = PIC(unicode_characters); - unsigned int n = PIC_LANGU(language_pack)->nb_characters; -#else //defined(HAVE_LANGUAGE_PACK) - const bagl_font_unicode_character_t *characters = PIC_CHARU(font_unicode->characters); - unsigned int n = C_unicode_characters_count; -#endif //defined(HAVE_LANGUAGE_PACK) - // For the moment, let just parse the full array, but at the end let use - // binary search as data are sorted by unicode value ! - for (unsigned i=0; i < n-1; i++, characters++) { - if ((PIC_CHARU(characters))->char_unicode == unicode) { - // Compute the number of bytes used to display this character - unicode_byte_count = (PIC_CHARU(characters+1))->bitmap_offset - \ - (PIC_CHARU(characters))->bitmap_offset; - return (PIC_CHARU(characters)); + const bagl_font_unicode_character_t *characters = PIC(unicode_characters); + unsigned int n = PIC_LANGU(language_pack)->nb_characters; +#else // defined(HAVE_LANGUAGE_PACK) + const bagl_font_unicode_character_t *characters = PIC_CHARU(font_unicode->characters); + unsigned int n = C_unicode_characters_count; +#endif // defined(HAVE_LANGUAGE_PACK) + // For the moment, let just parse the full array, but at the end let use + // binary search as data are sorted by unicode value ! + for (unsigned i = 0; i < n - 1; i++, characters++) { + if ((PIC_CHARU(characters))->char_unicode == unicode) { + // Compute the number of bytes used to display this character + unicode_byte_count = (PIC_CHARU(characters + 1))->bitmap_offset + - (PIC_CHARU(characters))->bitmap_offset; + return (PIC_CHARU(characters)); + } } - } - // By default, let's use the last Unicode character, which should be the - // 0x00FFFD one, used to replace unrecognized or unrepresentable character. - - // Compute the number of bytes used to display this character - unicode_byte_count = font_unicode->bitmap_len - \ - (PIC_CHARU(characters))->bitmap_offset; - return (PIC_CHARU(characters)); + // By default, let's use the last Unicode character, which should be the + // 0x00FFFD one, used to replace unrecognized or unrepresentable character. + + // Compute the number of bytes used to display this character + unicode_byte_count = font_unicode->bitmap_len - (PIC_CHARU(characters))->bitmap_offset; + return (PIC_CHARU(characters)); } // ---------------------------------------------------------------------------- -bagl_font_t const *toggle_bold(unsigned short *font_id) { - - bagl_font_t const *font; - unsigned short id = *font_id & BAGL_FONT_ID_MASK; - unsigned short alignment = *font_id & ~(BAGL_FONT_ID_MASK); +bagl_font_t const *toggle_bold(unsigned short *font_id) +{ + bagl_font_t const *font; + unsigned short id = *font_id & BAGL_FONT_ID_MASK; + unsigned short alignment = *font_id & ~(BAGL_FONT_ID_MASK); - switch (id) { - case BAGL_FONT_OPEN_SANS_REGULAR_11px: - id = BAGL_FONT_OPEN_SANS_EXTRABOLD_11px; - break; - case BAGL_FONT_OPEN_SANS_EXTRABOLD_11px: - default: - id = BAGL_FONT_OPEN_SANS_REGULAR_11px; - break; - } - *font_id = id | alignment; + switch (id) { + case BAGL_FONT_OPEN_SANS_REGULAR_11px: + id = BAGL_FONT_OPEN_SANS_EXTRABOLD_11px; + break; + case BAGL_FONT_OPEN_SANS_EXTRABOLD_11px: + default: + id = BAGL_FONT_OPEN_SANS_REGULAR_11px; + break; + } + *font_id = id | alignment; - // Update fonts - font = bagl_get_font(*font_id); + // Update fonts + font = bagl_get_font(*font_id); - font_unicode = bagl_get_font_unicode(*font_id); - if (font_unicode == NULL) { - font = NULL; - } + font_unicode = bagl_get_font_unicode(*font_id); + if (font_unicode == NULL) { + font = NULL; + } - return font; + return font; } -#endif //defined(HAVE_UNICODE_SUPPORT) +#endif // defined(HAVE_UNICODE_SUPPORT) // -------------------------------------------------------------------------------------- // return the width of a text (first line only) for alignment processing -unsigned short bagl_compute_line_width(unsigned short font_id, unsigned short width, const void * text, unsigned char text_length, unsigned char text_encoding) { - - // We will mutualise code from bagl_draw_string(smaller, easier to maintain): - return (unsigned short)bagl_draw_string(font_id, 0, 0, MAGIC_XY, MAGIC_XY, width, 0, text, text_length, text_encoding); +unsigned short bagl_compute_line_width(unsigned short font_id, + unsigned short width, + const void *text, + unsigned char text_length, + unsigned char text_encoding) +{ + // We will mutualise code from bagl_draw_string(smaller, easier to maintain): + return (unsigned short) bagl_draw_string( + font_id, 0, 0, MAGIC_XY, MAGIC_XY, width, 0, text, text_length, text_encoding); } // -------------------------------------------------------------------------------------- // draw char until a char fit before reaching width // TODO support hyphenation ?? -int bagl_draw_string(unsigned short font_id, unsigned int fgcolor, unsigned int bgcolor, int x, int y, unsigned int width, unsigned int height, const void* text, unsigned int text_length, unsigned char text_encoding) { - // This function can be called just to compute line width: set a flag. - unsigned char dont_draw = 0; - // Is it a 'magic number' telling we just want to compute line width? - if (x == MAGIC_XY && y == MAGIC_XY) { - x = y = 0; - dont_draw = 1; - } - - int xx; - unsigned int colors[16]; - colors[0] = bgcolor; - colors[1] = fgcolor; - unsigned int ch = 0; - unsigned int bpp; - const unsigned char *txt = text; +int bagl_draw_string(unsigned short font_id, + unsigned int fgcolor, + unsigned int bgcolor, + int x, + int y, + unsigned int width, + unsigned int height, + const void *text, + unsigned int text_length, + unsigned char text_encoding) +{ + // This function can be called just to compute line width: set a flag. + unsigned char dont_draw = 0; + // Is it a 'magic number' telling we just want to compute line width? + if (x == MAGIC_XY && y == MAGIC_XY) { + x = y = 0; + dont_draw = 1; + } + + int xx; + unsigned int colors[16]; + colors[0] = bgcolor; + colors[1] = fgcolor; + unsigned int ch = 0; + unsigned int bpp; + const unsigned char *txt = text; #if defined(HAVE_UNICODE_SUPPORT) - // Make sure font_unicode is recomputed using current language pack - font_unicode = NULL; -#else //defined(HAVE_UNICODE_SUPPORT) - UNUSED(text_encoding); -#endif //defined(HAVE_UNICODE_SUPPORT) - - const bagl_font_t *font = bagl_get_font(font_id); - if (font == NULL) { - return 0; - } - bpp = font->bpp; + // Make sure font_unicode is recomputed using current language pack + font_unicode = NULL; +#else // defined(HAVE_UNICODE_SUPPORT) + UNUSED(text_encoding); +#endif // defined(HAVE_UNICODE_SUPPORT) + + const bagl_font_t *font = bagl_get_font(font_id); + if (font == NULL) { + return 0; + } + bpp = font->bpp; #if defined(HAVE_UNICODE_SUPPORT) - unsigned int unicode = 0; - font_unicode = bagl_get_font_unicode(font_id); - if (font_unicode == NULL) { - return 0; - } -#endif //defined(HAVE_UNICODE_SUPPORT) + unsigned int unicode = 0; + font_unicode = bagl_get_font_unicode(font_id); + if (font_unicode == NULL) { + return 0; + } +#endif // defined(HAVE_UNICODE_SUPPORT) #ifdef BAGL_MULTICHROME - if (bpp > 1) { - // fgcolor = 0x7e7ecc - // bgcolor = 0xeca529 - // $1 = {0xeca529, 0xc6985f, 0xa28b95, 0x7e7ecc} - - unsigned int color_count = 1<>(off*8))&0xFF; - int cbg = (bgcolor>>(off*8))&0xFF; - - int crange = MAX(cfg,cbg)-MIN(cfg,cbg)+1; - int cinc = crange/(color_count-1UL); - - if (cfg > cbg) { - unsigned int i; - for (i=1; i < color_count-1UL; i++) { - colors[i] |= MIN(0xFF, cbg+i*cinc)<<(off*8); - } - } - else { - unsigned int i; + if (bpp > 1) { + // fgcolor = 0x7e7ecc + // bgcolor = 0xeca529 + // $1 = {0xeca529, 0xc6985f, 0xa28b95, 0x7e7ecc} + + unsigned int color_count = 1 << bpp; + memset(colors, 0, sizeof(colors)); + colors[0] = bgcolor; + colors[color_count - 1] = fgcolor; + + // compute for all base colors + int off; + for (off = 0; off < 3; off++) { + int cfg = (fgcolor >> (off * 8)) & 0xFF; + int cbg = (bgcolor >> (off * 8)) & 0xFF; + + int crange = MAX(cfg, cbg) - MIN(cfg, cbg) + 1; + int cinc = crange / (color_count - 1UL); + + if (cfg > cbg) { + unsigned int i; + for (i = 1; i < color_count - 1UL; i++) { + colors[i] |= MIN(0xFF, cbg + i * cinc) << (off * 8); + } + } + else { + unsigned int i; - for (i=1; i < color_count-1UL; i++) { - colors[i] |= MIN(0xFF, cfg+(color_count-1UL-i)*cinc)<<(off*8); + for (i = 1; i < color_count - 1UL; i++) { + colors[i] |= MIN(0xFF, cfg + (color_count - 1UL - i) * cinc) << (off * 8); + } + } } - } } - } -#endif // BAGL_MULTICHROME // for the blue - - // always comparing this way, very optimized etc - width += x; - height += y; +#endif // BAGL_MULTICHROME // for the blue - // initialize first index - xx = x; + // always comparing this way, very optimized etc + width += x; + height += y; - // depending on encoding - while (text_length--) { + // initialize first index + xx = x; - ch = *txt++; + // depending on encoding + while (text_length--) { + ch = *txt++; #if defined(HAVE_UNICODE_SUPPORT) - if (text_encoding == BAGL_ENCODING_UTF8) { - // Handle UTF-8 decoding (RFC3629): (https://www.ietf.org/rfc/rfc3629.txt - // Char. number range | UTF-8 octet sequence - // (hexadecimal) | (binary) - // --------------------+--------------------------------------------- - // 0000 0000-0000 007F | 0xxxxxxx - // 0000 0080-0000 07FF | 110xxxxx 10xxxxxx - // 0000 0800-0000 FFFF | 1110xxxx 10xxxxxx 10xxxxxx - // 0001 0000-0010 FFFF | 11110xxx 10xxxxxx 10xxxxxx 10xxxxxx - - // 4 bytes UTF-8, Unicode 0x1000 to 0x1FFFF - if (ch >= 0xF0 && text_length >= 3) { - unicode = (ch & 0x07) << 18; - unicode |= (*txt++ & 0x3F) << 12; - unicode |= (*txt++ & 0x3F) << 6; - unicode |= (*txt++ & 0x3F); - text_length -= 3; - - // 3 bytes UTF-8, Unicode 0x800 to 0xFFFF - } else if (ch >= 0xE0 && text_length >= 2) { - unicode = (ch & 0x0F) << 12; - unicode |= (*txt++ & 0x3F) << 6; - unicode |= (*txt++ & 0x3F); - text_length -= 2; - - // 2 bytes UTF-8, Unicode 0x80 to 0x7FF - // (0xC0 & 0xC1 are unused and can be used to store something else) - } else if (ch >= 0xC2 && text_length >= 1) { - unicode = (ch & 0x1F) << 6; - unicode |= (*txt++ & 0x3F); - text_length -= 1; - - } else { - unicode = 0; - } - } -#endif //defined(HAVE_UNICODE_SUPPORT) - - unsigned char ch_height = font->height; - int ch_offset_x = 0; - int ch_x_max = 0; - int ch_offset_y = 0; - unsigned char ch_width = 0; - uint16_t ch_bits = 0; - const unsigned char * ch_bitmap = NULL; - int ch_y = y; - - if (ch < font->first_char || ch > font->last_char) { + if (text_encoding == BAGL_ENCODING_UTF8) { + // Handle UTF-8 decoding (RFC3629): (https://www.ietf.org/rfc/rfc3629.txt + // Char. number range | UTF-8 octet sequence + // (hexadecimal) | (binary) + // --------------------+--------------------------------------------- + // 0000 0000-0000 007F | 0xxxxxxx + // 0000 0080-0000 07FF | 110xxxxx 10xxxxxx + // 0000 0800-0000 FFFF | 1110xxxx 10xxxxxx 10xxxxxx + // 0001 0000-0010 FFFF | 11110xxx 10xxxxxx 10xxxxxx 10xxxxxx + + // 4 bytes UTF-8, Unicode 0x1000 to 0x1FFFF + if (ch >= 0xF0 && text_length >= 3) { + unicode = (ch & 0x07) << 18; + unicode |= (*txt++ & 0x3F) << 12; + unicode |= (*txt++ & 0x3F) << 6; + unicode |= (*txt++ & 0x3F); + text_length -= 3; + + // 3 bytes UTF-8, Unicode 0x800 to 0xFFFF + } + else if (ch >= 0xE0 && text_length >= 2) { + unicode = (ch & 0x0F) << 12; + unicode |= (*txt++ & 0x3F) << 6; + unicode |= (*txt++ & 0x3F); + text_length -= 2; + + // 2 bytes UTF-8, Unicode 0x80 to 0x7FF + // (0xC0 & 0xC1 are unused and can be used to store something else) + } + else if (ch >= 0xC2 && text_length >= 1) { + unicode = (ch & 0x1F) << 6; + unicode |= (*txt++ & 0x3F); + text_length -= 1; + } + else { + unicode = 0; + } + } +#endif // defined(HAVE_UNICODE_SUPPORT) + + unsigned char ch_height = font->height; + int ch_offset_x = 0; + int ch_x_max = 0; + int ch_offset_y = 0; + unsigned char ch_width = 0; + uint16_t ch_bits = 0; + const unsigned char *ch_bitmap = NULL; + int ch_y = y; + + if (ch < font->first_char || ch > font->last_char) { #if defined(HAVE_UNICODE_SUPPORT) - // All escape sequences \n, \f and \e should have been removed before. - switch(ch) { - case '\b': // Bold toggle: turn Bold On/Off - if ((font=toggle_bold(&font_id)) == NULL) { - return 0; - } - continue; - case '\e': // Escape character => ignore it and the extra byte. - if (text_length >= 1) { // Take care of \e without additional byte! - ++txt; - text_length -= 1; - } - continue; - } + // All escape sequences \n, \f and \e should have been removed before. + switch (ch) { + case '\b': // Bold toggle: turn Bold On/Off + if ((font = toggle_bold(&font_id)) == NULL) { + return 0; + } + continue; + case '\e': // Escape character => ignore it and the extra byte. + if (text_length >= 1) { // Take care of \e without additional byte! + ++txt; + text_length -= 1; + } + continue; + } - if (unicode) { - const bagl_font_unicode_character_t *character; - character = get_unicode_character(unicode); - ch_width = character->width; - // Number of bits needed to display this character - ch_bits = unicode_byte_count * 8; + if (unicode) { + const bagl_font_unicode_character_t *character; + character = get_unicode_character(unicode); + ch_width = character->width; + // Number of bits needed to display this character + ch_bits = unicode_byte_count * 8; #if defined(HAVE_LANGUAGE_PACK) - ch_bitmap = PIC_BMPU(unicode_bitmap); -#else //defined(HAVE_LANGUAGE_PACK) - ch_bitmap = PIC_BMPU(font_unicode->bitmap); -#endif //defined(HAVE_LANGUAGE_PACK) - ch_bitmap += character->bitmap_offset; - - ch_offset_x = (uint16_t)character->x_min_offset; - ch_x_max = (uint16_t)character->x_max_offset; - ch_offset_y = (unsigned int)character->y_min_offset; - // Take in account the difference of baseline with reference value - ch_offset_y -= (int)font_unicode->baseline - (int)FONT_BASELINE; - ch_width -= character->x_min_offset; - ch_width -= ch_x_max; - } else -#endif //defined(HAVE_UNICODE_SUPPORT) - { - if (ch >= 0xC0) { - ch_width = ch & 0x3F; + ch_bitmap = PIC_BMPU(unicode_bitmap); +#else // defined(HAVE_LANGUAGE_PACK) + ch_bitmap = PIC_BMPU(font_unicode->bitmap); +#endif // defined(HAVE_LANGUAGE_PACK) + ch_bitmap += character->bitmap_offset; + + ch_offset_x = (uint16_t) character->x_min_offset; + ch_x_max = (uint16_t) character->x_max_offset; + ch_offset_y = (unsigned int) character->y_min_offset; + // Take in account the difference of baseline with reference value + ch_offset_y -= (int) font_unicode->baseline - (int) FONT_BASELINE; + ch_width -= character->x_min_offset; + ch_width -= ch_x_max; + } + else +#endif // defined(HAVE_UNICODE_SUPPORT) + { + if (ch >= 0xC0) { + ch_width = ch & 0x3F; + } + else if (ch >= 0x80) { + // open the glyph font + const bagl_font_t *font_symbols + = bagl_get_font((ch & 0x20) ? BAGL_FONT_SYMBOLS_1 : BAGL_FONT_SYMBOLS_0); + if (font_symbols != NULL) { + ch_bitmap = &PIC_BMP( + font_symbols->bitmap)[PIC_CHAR(font_symbols->characters)[ch & 0x1F] + .bitmap_offset]; + ch_width = PIC_CHAR(font_symbols->characters)[ch & 0x1F].width; + ch_height = font_symbols->height; + // align baselines + ch_y = y + font->baseline - font_symbols->baseline; + } + } + ch_bits = bpp * ch_width * ch_height; + } } - else if (ch >= 0x80) { - // open the glyph font - const bagl_font_t *font_symbols = bagl_get_font((ch&0x20)?BAGL_FONT_SYMBOLS_1:BAGL_FONT_SYMBOLS_0); - if (font_symbols != NULL) { - ch_bitmap = &PIC_BMP(font_symbols->bitmap)[PIC_CHAR(font_symbols->characters)[ch & 0x1F].bitmap_offset]; - ch_width = PIC_CHAR(font_symbols->characters)[ch & 0x1F].width; - ch_height = font_symbols->height; - // align baselines - ch_y = y + font->baseline - font_symbols->baseline; - } + else { + // retrieve the char bitmap + ch -= font->first_char; + ch_bitmap = &PIC_BMP(font->bitmap)[PIC_CHAR(font->characters)[ch].bitmap_offset]; + + // Number of bits needed to display this character + if (ch == (unsigned int) (font->last_char - font->first_char)) { + ch_bits + = font->bitmap_len - (uint16_t) (PIC_CHAR(font->characters)[ch].bitmap_offset); + } + else { + ch_bits = PIC_CHAR(font->characters)[ch + 1].bitmap_offset + - PIC_CHAR(font->characters)[ch].bitmap_offset; + } + ch_bits *= 8; + + ch_width = PIC_CHAR(font->characters)[ch].width; + + ch_offset_x = (uint16_t) PIC_CHAR(font->characters)[ch].x_min_offset; + ch_x_max = PIC_CHAR(font->characters)[ch].x_max_offset; + ch_offset_y = (uint16_t) PIC_CHAR(font->characters)[ch].y_min_offset; + // Take in account the difference of baseline with reference value + ch_offset_y -= (int) font->baseline - (int) FONT_BASELINE; + ch_width -= PIC_CHAR(font->characters)[ch].x_min_offset; + ch_width -= ch_x_max; } - ch_bits = bpp*ch_width*ch_height; - } - } - else { - // retrieve the char bitmap - ch -= font->first_char; - ch_bitmap = &PIC_BMP(font->bitmap)[PIC_CHAR(font->characters)[ch].bitmap_offset]; - - // Number of bits needed to display this character - if (ch == (unsigned int)(font->last_char - font->first_char)) { - ch_bits = font->bitmap_len - (uint16_t)(PIC_CHAR(font->characters)[ch].bitmap_offset); - } else { - ch_bits = PIC_CHAR(font->characters)[ch+1].bitmap_offset - PIC_CHAR(font->characters)[ch].bitmap_offset; - } - ch_bits *= 8; - ch_width = PIC_CHAR(font->characters)[ch].width; + if (dont_draw) { + // go to next line if needed + if ((int) width > 0 && (xx + ch_offset_x + (int) ch_width) > (int) width) { + return xx; + } + // prepare for next char + xx += ch_offset_x + (int) ch_width + ch_x_max; + } + else { + // go to next line if needed + if ((xx + ch_offset_x + (int) ch_width) > (int) width) { + y += FONT_HEIGHT; // no interleave + + // IGNORED for first line + if ((y + ch_offset_y + (int) ch_height) > (int) height) { + // we're writing half height of the last line ... probably better to put some + // dashes + return (y << 16) | (xx & 0xFFFF); + } + + // newline starts back at first x offset + xx = x; + ch_y = y; + } - ch_offset_x = (uint16_t)PIC_CHAR(font->characters)[ch].x_min_offset; - ch_x_max = PIC_CHAR(font->characters)[ch].x_max_offset; - ch_offset_y = (uint16_t)PIC_CHAR(font->characters)[ch].y_min_offset; - // Take in account the difference of baseline with reference value - ch_offset_y -= (int)font->baseline - (int)FONT_BASELINE; - ch_width -= PIC_CHAR(font->characters)[ch].x_min_offset; - ch_width -= ch_x_max; + /* IGNORED for first line + if (y + ch_height > height) { + // we're writing half height of the last line ... probably better to put some dashes + return; + } + */ + + // chars are storred LSB to MSB in each char, packed chars. horizontal scan + if (ch_bitmap) { + bagl_hal_draw_bitmap_within_rect(xx + ch_offset_x, + ch_y + ch_offset_y, + ch_width, + ch_height, + (1 << bpp), + colors, + bpp, + ch_bitmap, + ch_bits); + } + else { + bagl_hal_draw_rect(bgcolor, xx, ch_y, ch_width, ch_height); + } + // prepare for next char + xx += ch_offset_x + (int) ch_width + ch_x_max; + } } if (dont_draw) { - // go to next line if needed - if ((int)width > 0 && (xx + ch_offset_x + (int)ch_width) > (int)width) { return xx; - } - // prepare for next char - xx += ch_offset_x + (int)ch_width + ch_x_max; - - } else { - // go to next line if needed - if ((xx + ch_offset_x + (int)ch_width) > (int)width) { - y += FONT_HEIGHT; // no interleave - - // IGNORED for first line - if ((y + ch_offset_y + (int)ch_height) > (int)height) { - // we're writing half height of the last line ... probably better to put some dashes - return (y<<16)|(xx&0xFFFF); - } - - // newline starts back at first x offset - xx = x; - ch_y = y; - } - - /* IGNORED for first line - if (y + ch_height > height) { - // we're writing half height of the last line ... probably better to put some dashes - return; - } - */ - - // chars are storred LSB to MSB in each char, packed chars. horizontal scan - if (ch_bitmap) { - bagl_hal_draw_bitmap_within_rect(xx + ch_offset_x, ch_y + ch_offset_y, ch_width, ch_height, (1< 0 && dradius > 0 /*&& xint <= yint*/); - - while( y <= x ) - { - if (octants & 1) { // - if (drawint) { - bagl_hal_draw_rect(colorint, x_center, y+y_center, x-(dradius-1), 1); - bagl_hal_draw_rect(color, x_center+x-(dradius-1), y+y_center, dradius, 1); - } - else { - bagl_hal_draw_rect(color, x_center, y+y_center-1, x, 1); - } - } - if (octants & 2) { // - if (drawint) { - if (last_x != x) { - bagl_hal_draw_rect(colorint, x_center, x+y_center, y-(dradius-1), 1); + int last_x; + int x = radius; + int y = 0; + int decisionOver2 = 1 - x; // Decision criterion divided by 2 evaluated at x=r, y=0 + int dradius = radius - radiusint; + last_x = x; + unsigned int drawint = (radiusint > 0 && dradius > 0 /*&& xint <= yint*/); + + while (y <= x) { + if (octants & 1) { // + if (drawint) { + bagl_hal_draw_rect(colorint, x_center, y + y_center, x - (dradius - 1), 1); + bagl_hal_draw_rect(color, x_center + x - (dradius - 1), y + y_center, dradius, 1); + } + else { + bagl_hal_draw_rect(color, x_center, y + y_center - 1, x, 1); + } } - bagl_hal_draw_rect(color, x_center+y-(dradius-1), x+y_center, dradius, 1); - } - else { - bagl_hal_draw_rect(color, x_center, x+y_center-1, y, 1); - } - } - if (octants & 4) { // - if (drawint) { - bagl_hal_draw_rect(colorint, x_center-x, y+y_center, x-(dradius-1), 1); - bagl_hal_draw_rect(color, x_center-x-(dradius-1), y+y_center, dradius, 1); - } - else { - bagl_hal_draw_rect(color, x_center-x, y+y_center-1, x, 1); - } - } - if (octants & 8) { // - if (drawint) { - if (last_x != x) { - bagl_hal_draw_rect(colorint, x_center-y, x+y_center, y-(dradius-1), 1); + if (octants & 2) { // + if (drawint) { + if (last_x != x) { + bagl_hal_draw_rect(colorint, x_center, x + y_center, y - (dradius - 1), 1); + } + bagl_hal_draw_rect(color, x_center + y - (dradius - 1), x + y_center, dradius, 1); + } + else { + bagl_hal_draw_rect(color, x_center, x + y_center - 1, y, 1); + } } - bagl_hal_draw_rect(color, x_center-y-(dradius-1), x+y_center, dradius, 1); - } - else { - bagl_hal_draw_rect(color, x_center-y, x+y_center-1, y, 1); - } - } - if (octants & 16) { // - if (drawint) { - bagl_hal_draw_rect(colorint, x_center, y_center-y, x-(dradius-1), 1); - bagl_hal_draw_rect(color, x_center+x-(dradius-1), y_center-y, dradius, 1); - } - else { - bagl_hal_draw_rect(color, x_center, y_center-y, x, 1); - } - } - if (octants & 32) { // - if (drawint) { - if (last_x != x) { - bagl_hal_draw_rect(colorint, x_center, y_center-x, y-(dradius-1), 1); + if (octants & 4) { // + if (drawint) { + bagl_hal_draw_rect(colorint, x_center - x, y + y_center, x - (dradius - 1), 1); + bagl_hal_draw_rect(color, x_center - x - (dradius - 1), y + y_center, dradius, 1); + } + else { + bagl_hal_draw_rect(color, x_center - x, y + y_center - 1, x, 1); + } } - bagl_hal_draw_rect(color, x_center+y-(dradius-1), y_center-x, dradius, 1); - } - else { - bagl_hal_draw_rect(color, x_center, y_center-x, y, 1); - } - } - if (octants & 64) { // - if (drawint) { - bagl_hal_draw_rect(colorint, x_center-x, y_center-y, x-(dradius-1), 1); - bagl_hal_draw_rect(color, x_center-x-(dradius-1), y_center-y, dradius, 1); - } - else { - bagl_hal_draw_rect(color, x_center-x, y_center-y, x, 1); - } - } - if (octants & 128) { // - if (drawint) { - if (last_x != x) { - bagl_hal_draw_rect(colorint, x_center-y, y_center-x, y-(dradius-1), 1); + if (octants & 8) { // + if (drawint) { + if (last_x != x) { + bagl_hal_draw_rect(colorint, x_center - y, x + y_center, y - (dradius - 1), 1); + } + bagl_hal_draw_rect(color, x_center - y - (dradius - 1), x + y_center, dradius, 1); + } + else { + bagl_hal_draw_rect(color, x_center - y, x + y_center - 1, y, 1); + } + } + if (octants & 16) { // + if (drawint) { + bagl_hal_draw_rect(colorint, x_center, y_center - y, x - (dradius - 1), 1); + bagl_hal_draw_rect(color, x_center + x - (dradius - 1), y_center - y, dradius, 1); + } + else { + bagl_hal_draw_rect(color, x_center, y_center - y, x, 1); + } + } + if (octants & 32) { // + if (drawint) { + if (last_x != x) { + bagl_hal_draw_rect(colorint, x_center, y_center - x, y - (dradius - 1), 1); + } + bagl_hal_draw_rect(color, x_center + y - (dradius - 1), y_center - x, dradius, 1); + } + else { + bagl_hal_draw_rect(color, x_center, y_center - x, y, 1); + } + } + if (octants & 64) { // + if (drawint) { + bagl_hal_draw_rect(colorint, x_center - x, y_center - y, x - (dradius - 1), 1); + bagl_hal_draw_rect(color, x_center - x - (dradius - 1), y_center - y, dradius, 1); + } + else { + bagl_hal_draw_rect(color, x_center - x, y_center - y, x, 1); + } + } + if (octants & 128) { // + if (drawint) { + if (last_x != x) { + bagl_hal_draw_rect(colorint, x_center - y, y_center - x, y - (dradius - 1), 1); + } + bagl_hal_draw_rect(color, x_center - y - (dradius - 1), y_center - x, dradius, 1); + } + else { + bagl_hal_draw_rect(color, x_center - y, y_center - x, y, 1); + } } - bagl_hal_draw_rect(color, x_center-y-(dradius-1), y_center-x, dradius, 1); - } - else { - bagl_hal_draw_rect(color, x_center-y, y_center-x, y, 1); - } - } - last_x = x; - y++; - if (decisionOver2<=0) - { - decisionOver2 += 2 * y + 1; // Change in decision criterion for y -> y+1 - } - else - { - x--; - decisionOver2 += 2 * (y - x) + 1; // Change for y -> y+1, x -> x-1 + last_x = x; + y++; + if (decisionOver2 <= 0) { + decisionOver2 += 2 * y + 1; // Change in decision criterion for y -> y+1 + } + else { + x--; + decisionOver2 += 2 * (y - x) + 1; // Change for y -> y+1, x -> x-1 + } } - } } // -------------------------------------------------------------------------------------- #ifdef HAVE_BAGL_GLYPH_ARRAY -void bagl_set_glyph_array(const bagl_glyph_array_entry_t* array, unsigned int count) { - G_glyph_array = array; - G_glyph_count = count; +void bagl_set_glyph_array(const bagl_glyph_array_entry_t *array, unsigned int count) +{ + G_glyph_array = array; + G_glyph_count = count; } -#endif // HAVE_BAGL_GLYPH_ARRAY +#endif // HAVE_BAGL_GLYPH_ARRAY // -------------------------------------------------------------------------------------- -void bagl_draw_with_context(const bagl_component_t* component, const void* context, unsigned short context_length, unsigned char context_encoding) { - //unsigned char comp_idx; - int halignment=0; - int valignment=0; - int baseline=0; - unsigned int height_to_draw=0; - int strwidth = 0; - unsigned int ellipsis_1_len = 0; +void bagl_draw_with_context(const bagl_component_t *component, + const void *context, + unsigned short context_length, + unsigned char context_encoding) +{ + // unsigned char comp_idx; + int halignment = 0; + int valignment = 0; + int baseline = 0; + unsigned int height_to_draw = 0; + int strwidth = 0; + unsigned int ellipsis_1_len = 0; #ifdef HAVE_BAGL_ELLIPSIS - const char* ellipsis_2_start = NULL; -#endif // HAVE_BAGL_ELLIPSIS + const char *ellipsis_2_start = NULL; +#endif // HAVE_BAGL_ELLIPSIS #ifdef HAVE_BAGL_GLYPH_ARRAY - const bagl_glyph_array_entry_t* glyph=NULL; -#endif // HAVE_BAGL_GLYPH_ARRAY + const bagl_glyph_array_entry_t *glyph = NULL; +#endif // HAVE_BAGL_GLYPH_ARRAY - // DESIGN NOTE: always consider drawing onto a bg color filled image. (done upon undraw) + // DESIGN NOTE: always consider drawing onto a bg color filled image. (done upon undraw) - /* - // check if userid already exist, if yes, reuse entry - for (comp_idx=0; comp_idx < BAGL_COMPONENT_MAXCOUNT; comp_idx++) { - if (bagl_components[comp_idx].userid == component->userid) { - goto idx_ok; + /* + // check if userid already exist, if yes, reuse entry + for (comp_idx=0; comp_idx < BAGL_COMPONENT_MAXCOUNT; comp_idx++) { + if (bagl_components[comp_idx].userid == component->userid) { + goto idx_ok; + } } - } - // find the first empty entry - for (comp_idx=0; comp_idx < BAGL_COMPONENT_MAXCOUNT; comp_idx++) { - if (bagl_components[comp_idx].userid == BAGL_NONE) { - goto idx_ok; + // find the first empty entry + for (comp_idx=0; comp_idx < BAGL_COMPONENT_MAXCOUNT; comp_idx++) { + if (bagl_components[comp_idx].userid == BAGL_NONE) { + goto idx_ok; + } } - } - // no more space :( - //BAGL_THROW(NO_SPACE); - return; + // no more space :( + //BAGL_THROW(NO_SPACE); + return; -idx_ok: - */ + idx_ok: + */ - // strip the flags to match kinds - unsigned int type = component->type&~(BAGL_TYPE_FLAGS_MASK); + // strip the flags to match kinds + unsigned int type = component->type & ~(BAGL_TYPE_FLAGS_MASK); #if defined(HAVE_INDEXED_STRINGS) - // BAGL_LABELINE_LOC are BAGL_LABELINE: - if (type == BAGL_LABELINE_LOC) { - type = BAGL_LABELINE; - } -#endif //defined(HAVE_INDEXED_STRINGS) - - // compute alignment if text provided and requiring special alignment - if (type != BAGL_ICON) { - const bagl_font_t* font = bagl_get_font(component->font_id); - if (font) { - baseline = font->baseline; - height_to_draw = component->height; - - if (context && context_length) { - // compute with some margin to fit other characters and check if ellipsis algorithm is required - strwidth = bagl_compute_line_width(component->font_id, component->width+100, context, context_length, context_encoding); - ellipsis_1_len = context_length; + // BAGL_LABELINE_LOC are BAGL_LABELINE: + if (type == BAGL_LABELINE_LOC) { + type = BAGL_LABELINE; + } +#endif // defined(HAVE_INDEXED_STRINGS) + + // compute alignment if text provided and requiring special alignment + if (type != BAGL_ICON) { + const bagl_font_t *font = bagl_get_font(component->font_id); + if (font) { + baseline = font->baseline; + height_to_draw = component->height; + + if (context && context_length) { + // compute with some margin to fit other characters and check if ellipsis algorithm + // is required + strwidth = bagl_compute_line_width(component->font_id, + component->width + 100, + context, + context_length, + context_encoding); + ellipsis_1_len = context_length; #ifdef HAVE_BAGL_ELLIPSIS - // ellipsis mode (ensure something is to be split!) - if (strwidth > component->width && context_length>4) { - unsigned int robin = 0; // remove char by char either on the left or right side - unsigned int dots_len = bagl_compute_line_width(component->font_id, 100 /*probably larger than ... whatever the font*/, "...", 3, context_encoding); - ellipsis_1_len = context_length/2; - ellipsis_2_start = ((const char*)context) + context_length/2; - // split line in 2 halves, strip a char from end of left part, and from start of right part, reassemble with ... , repeat until it fits. - // NOTE: algorithm is wrong if special blank chars are inserted, they should be removed first - while (strwidth > component->width && ellipsis_1_len && (context_length - ((const void *)ellipsis_2_start-(const void *)context) )) { - unsigned int left_part = bagl_compute_line_width(component->font_id, component->width, context, ellipsis_1_len, context_encoding); - unsigned int right_part = bagl_compute_line_width(component->font_id, component->width, ellipsis_2_start, (context_length - ((const void *)ellipsis_2_start-(const void *)context)), context_encoding); - // update to check and to compute alignment if needed - strwidth = left_part + dots_len + right_part; - // only start to split if the middle char if odd context_length removal is not sufficient - if (strwidth > component->width) { - // either remove a left char, OR remove a right char - switch(robin) { - case 0: - // remove a left char - ellipsis_1_len--; - break; - case 1: - // remove a right char - ellipsis_2_start++; - break; - } - robin = (robin+1)%2; + // ellipsis mode (ensure something is to be split!) + if (strwidth > component->width && context_length > 4) { + unsigned int robin = 0; // remove char by char either on the left or right side + unsigned int dots_len = bagl_compute_line_width( + component->font_id, + 100 /*probably larger than ... whatever the font*/, + "...", + 3, + context_encoding); + ellipsis_1_len = context_length / 2; + ellipsis_2_start = ((const char *) context) + context_length / 2; + // split line in 2 halves, strip a char from end of left part, and from start of + // right part, reassemble with ... , repeat until it fits. NOTE: algorithm is + // wrong if special blank chars are inserted, they should be removed first + while (strwidth > component->width && ellipsis_1_len + && (context_length + - ((const void *) ellipsis_2_start - (const void *) context))) { + unsigned int left_part = bagl_compute_line_width(component->font_id, + component->width, + context, + ellipsis_1_len, + context_encoding); + unsigned int right_part = bagl_compute_line_width( + component->font_id, + component->width, + ellipsis_2_start, + (context_length + - ((const void *) ellipsis_2_start - (const void *) context)), + context_encoding); + // update to check and to compute alignment if needed + strwidth = left_part + dots_len + right_part; + // only start to split if the middle char if odd context_length removal is + // not sufficient + if (strwidth > component->width) { + // either remove a left char, OR remove a right char + switch (robin) { + case 0: + // remove a left char + ellipsis_1_len--; + break; + case 1: + // remove a right char + ellipsis_2_start++; + break; + } + robin = (robin + 1) % 2; + } + } + // we've computed split positions + } +#endif // HAVE_BAGL_ELLIPSIS + + switch (component->font_id & BAGL_FONT_ALIGNMENT_HORIZONTAL_MASK) { + default: + case BAGL_FONT_ALIGNMENT_LEFT: + halignment = 0; + break; + case BAGL_FONT_ALIGNMENT_RIGHT: + halignment = MAX(0, component->width - strwidth); + break; + case BAGL_FONT_ALIGNMENT_CENTER: + // x xalign strwidth width + // ' ' ' ' + // ^ + // xalign = x+ (width/2) - (strwidth/2) => align -x + halignment = MAX(0, component->width / 2 - strwidth / 2); + break; + } + + switch (component->font_id & BAGL_FONT_ALIGNMENT_VERTICAL_MASK) { + default: + case BAGL_FONT_ALIGNMENT_TOP: + valignment = 0; + break; + case BAGL_FONT_ALIGNMENT_BOTTOM: + valignment = component->height - baseline; + break; + case BAGL_FONT_ALIGNMENT_MIDDLE: + // y yalign charheight height + // ' ' v ' ' + // baseline + // yalign = y+ (height/2) - (baseline/2) => align - y + valignment = component->height / 2 - baseline / 2 - 1; + break; + } } - } - // we've computed split positions } -#endif // HAVE_BAGL_ELLIPSIS - - switch (component->font_id & BAGL_FONT_ALIGNMENT_HORIZONTAL_MASK ) { - default: - case BAGL_FONT_ALIGNMENT_LEFT: - halignment = 0; - break; - case BAGL_FONT_ALIGNMENT_RIGHT: - halignment = MAX(0,component->width - strwidth); - break; - case BAGL_FONT_ALIGNMENT_CENTER: - // x xalign strwidth width - // ' ' ' ' - // ^ - // xalign = x+ (width/2) - (strwidth/2) => align -x - halignment = MAX(0,component->width/2 - strwidth/2); - break; - } - - switch (component->font_id & BAGL_FONT_ALIGNMENT_VERTICAL_MASK ) { - default: - case BAGL_FONT_ALIGNMENT_TOP: - valignment = 0; - break; - case BAGL_FONT_ALIGNMENT_BOTTOM: - valignment = component->height - baseline; - break; - case BAGL_FONT_ALIGNMENT_MIDDLE: - // y yalign charheight height - // ' ' v ' ' - // baseline - // yalign = y+ (height/2) - (baseline/2) => align - y - valignment = component->height/2 - baseline/2 - 1; - break; - } - } } - } - - unsigned int radius = component->radius; - radius = MIN(radius, MIN(component->width/2, component->height/2)); - - // Check the type only, ignore the touchable flag - switch (type) { - /* - button (B) - < |Icon|Space|Textstring| > - I.w W.w T.w - I.x = B.x+B.w/2-(I.w+W.w+T.w)/2 - W.x = I.x+I.w - T.x = W.x+W.w = I.x+I.w+W.w = B.x+B.w/2-(I.w+W.w+T.w)/2+I.w+W.w = B.x+B.w/2-T.w/2+(I.w+W.w)/2 - */ - // Following types are supposed to draw a rectangle or write text or both - case BAGL_BUTTON: - case BAGL_LABEL: - case BAGL_RECTANGLE: - case BAGL_LINE: - case BAGL_LABELINE: - if((type == BAGL_LINE) && (component->radius == 0)) { - bagl_hal_draw_rect(component->fgcolor, - component->x, component->y, - component->width, component->height); - break; - } + unsigned int radius = component->radius; + radius = MIN(radius, MIN(component->width / 2, component->height / 2)); + + // Check the type only, ignore the touchable flag + switch (type) { + /* + button (B) + < |Icon|Space|Textstring| > + I.w W.w T.w + I.x = B.x+B.w/2-(I.w+W.w+T.w)/2 + W.x = I.x+I.w + T.x = W.x+W.w = I.x+I.w+W.w = B.x+B.w/2-(I.w+W.w+T.w)/2+I.w+W.w = + B.x+B.w/2-T.w/2+(I.w+W.w)/2 + */ + + // Following types are supposed to draw a rectangle or write text or both + case BAGL_BUTTON: + case BAGL_LABEL: + case BAGL_RECTANGLE: + case BAGL_LINE: + case BAGL_LABELINE: + if ((type == BAGL_LINE) && (component->radius == 0)) { + bagl_hal_draw_rect(component->fgcolor, + component->x, + component->y, + component->width, + component->height); + break; + } - if ((type == BAGL_LABEL) || (type == BAGL_LABELINE)) { - /*if (component->fill == BAGL_FILL)*/ { + if ((type == BAGL_LABEL) || (type == BAGL_LABELINE)) { + /*if (component->fill == BAGL_FILL)*/ { #ifndef DISPLAY_FLOWS - bagl_hal_draw_rect(component->bgcolor, - component->x, component->y-(type==BAGL_LABELINE?(baseline):0), - component->width, (type==BAGL_LABELINE? height_to_draw : component->height)); -#endif //DISPLAY_FLOWS - } - } - else { - // Draw the rounded or not, filled or not rectangle - if (component->fill != BAGL_FILL) { - // inner - // centered top to bottom - bagl_hal_draw_rect(component->bgcolor, - component->x+radius, component->y, - component->width-2*radius, component->height); - // left to center rect - bagl_hal_draw_rect(component->bgcolor, - component->x, component->y+radius, - radius, component->height-2*radius); - // center rect to right - bagl_hal_draw_rect(component->bgcolor, - component->x+component->width-radius-1, component->y+radius, - radius, component->height-2*radius); - - // outline - // 4 rectangles (with last pixel of each corner not set) - bagl_hal_draw_rect(component->fgcolor, - component->x+radius, component->y, - component->width-2*radius, component->stroke); // top - bagl_hal_draw_rect(component->fgcolor, - component->x+radius, component->y+component->height-1, - component->width-2*radius, component->stroke); // bottom - bagl_hal_draw_rect(component->fgcolor, - component->x, component->y+radius, - component->stroke, component->height-2*radius); // left - bagl_hal_draw_rect(component->fgcolor, - component->x+component->width-1, component->y+radius, - component->stroke, component->height-2*radius); // right - } - else { - // centered top to bottom - bagl_hal_draw_rect(component->fgcolor, - component->x+radius, component->y, - component->width-2*radius, component->height); - // left to center rect - bagl_hal_draw_rect(component->fgcolor, - component->x, component->y+radius, - radius, component->height-2*radius); - - // center rect to right - bagl_hal_draw_rect(component->fgcolor, - component->x+component->width-radius, component->y+radius, - radius, component->height-2*radius); - } + bagl_hal_draw_rect( + component->bgcolor, + component->x, + component->y - (type == BAGL_LABELINE ? (baseline) : 0), + component->width, + (type == BAGL_LABELINE ? height_to_draw : component->height)); +#endif // DISPLAY_FLOWS + } + } + else { + // Draw the rounded or not, filled or not rectangle + if (component->fill != BAGL_FILL) { + // inner + // centered top to bottom + bagl_hal_draw_rect(component->bgcolor, + component->x + radius, + component->y, + component->width - 2 * radius, + component->height); + // left to center rect + bagl_hal_draw_rect(component->bgcolor, + component->x, + component->y + radius, + radius, + component->height - 2 * radius); + // center rect to right + bagl_hal_draw_rect(component->bgcolor, + component->x + component->width - radius - 1, + component->y + radius, + radius, + component->height - 2 * radius); + + // outline + // 4 rectangles (with last pixel of each corner not set) + bagl_hal_draw_rect(component->fgcolor, + component->x + radius, + component->y, + component->width - 2 * radius, + component->stroke); // top + bagl_hal_draw_rect(component->fgcolor, + component->x + radius, + component->y + component->height - 1, + component->width - 2 * radius, + component->stroke); // bottom + bagl_hal_draw_rect(component->fgcolor, + component->x, + component->y + radius, + component->stroke, + component->height - 2 * radius); // left + bagl_hal_draw_rect(component->fgcolor, + component->x + component->width - 1, + component->y + radius, + component->stroke, + component->height - 2 * radius); // right + } + else { + // centered top to bottom + bagl_hal_draw_rect(component->fgcolor, + component->x + radius, + component->y, + component->width - 2 * radius, + component->height); + // left to center rect + bagl_hal_draw_rect(component->fgcolor, + component->x, + component->y + radius, + radius, + component->height - 2 * radius); + + // center rect to right + bagl_hal_draw_rect(component->fgcolor, + component->x + component->width - radius, + component->y + radius, + radius, + component->height - 2 * radius); + } #ifndef DISPLAY_FLOWS - // draw corners - if (radius > 1) { - unsigned int radiusint = 0; - // carve round when not filling - if ((component->fill != BAGL_FILL) && (component->stroke < radius)) { - radiusint = radius-component->stroke; - } - bagl_draw_circle_helper(component->fgcolor, - component->x+radius, - component->y+radius, - radius, BAGL_FILL_CIRCLE_PI2_PI, radiusint, - component->bgcolor); - bagl_draw_circle_helper(component->fgcolor, - component->x+component->width-radius-component->stroke, - component->y+radius, - radius, BAGL_FILL_CIRCLE_0_PI2, radiusint, - component->bgcolor); - bagl_draw_circle_helper(component->fgcolor, - component->x+radius, - component->y+component->height-radius-component->stroke, - radius, BAGL_FILL_CIRCLE_PI_3PI2, radiusint, - component->bgcolor); - bagl_draw_circle_helper(component->fgcolor, - component->x+component->width-radius-component->stroke, - component->y+component->height-radius-component->stroke, - radius, BAGL_FILL_CIRCLE_3PI2_2PI, radiusint, - component->bgcolor); - } -#endif //DISPLAY_FLOWS - } - - if (type == BAGL_LINE) { - // No text for this type - break; - } + // draw corners + if (radius > 1) { + unsigned int radiusint = 0; + // carve round when not filling + if ((component->fill != BAGL_FILL) && (component->stroke < radius)) { + radiusint = radius - component->stroke; + } + bagl_draw_circle_helper(component->fgcolor, + component->x + radius, + component->y + radius, + radius, + BAGL_FILL_CIRCLE_PI2_PI, + radiusint, + component->bgcolor); + bagl_draw_circle_helper( + component->fgcolor, + component->x + component->width - radius - component->stroke, + component->y + radius, + radius, + BAGL_FILL_CIRCLE_0_PI2, + radiusint, + component->bgcolor); + bagl_draw_circle_helper( + component->fgcolor, + component->x + radius, + component->y + component->height - radius - component->stroke, + radius, + BAGL_FILL_CIRCLE_PI_3PI2, + radiusint, + component->bgcolor); + bagl_draw_circle_helper( + component->fgcolor, + component->x + component->width - radius - component->stroke, + component->y + component->height - radius - component->stroke, + radius, + BAGL_FILL_CIRCLE_3PI2_2PI, + radiusint, + component->bgcolor); + } +#endif // DISPLAY_FLOWS + } - // Text display - if (context && context_length) { - unsigned int pos = 0; - unsigned int fgcolor = component->fgcolor; - unsigned int bgcolor = component->bgcolor; - - // Invert colors of text when rectangle/button is filled - if ( ((type == BAGL_BUTTON) || (type == BAGL_RECTANGLE)) - && (component->fill == BAGL_FILL)) { - fgcolor = component->bgcolor; - bgcolor = component->fgcolor; - } + if (type == BAGL_LINE) { + // No text for this type + break; + } - pos = bagl_draw_string(component->font_id, - fgcolor, bgcolor, - component->x + halignment, - component->y + ((type==BAGL_LABELINE)?-(baseline):valignment), - component->width - halignment, - component->height - ((type==BAGL_LABELINE)?0:valignment), - context, - ellipsis_1_len, - context_encoding); + // Text display + if (context && context_length) { + unsigned int pos = 0; + unsigned int fgcolor = component->fgcolor; + unsigned int bgcolor = component->bgcolor; + + // Invert colors of text when rectangle/button is filled + if (((type == BAGL_BUTTON) || (type == BAGL_RECTANGLE)) + && (component->fill == BAGL_FILL)) { + fgcolor = component->bgcolor; + bgcolor = component->fgcolor; + } + + pos = bagl_draw_string( + component->font_id, + fgcolor, + bgcolor, + component->x + halignment, + component->y + ((type == BAGL_LABELINE) ? -(baseline) : valignment), + component->width - halignment, + component->height - ((type == BAGL_LABELINE) ? 0 : valignment), + context, + ellipsis_1_len, + context_encoding); #ifdef HAVE_BAGL_ELLIPSIS - if (ellipsis_2_start) { - // draw ellipsis - pos = bagl_draw_string(component->font_id, - fgcolor, bgcolor, - (pos & 0xFFFF), - component->y + ((type==BAGL_LABELINE)?-(baseline):valignment), - component->width - halignment, - component->height - (type==BAGL_LABELINE?0:valignment), - "...", - 3, - context_encoding); - // draw the right part - bagl_draw_string(component->font_id, - fgcolor, bgcolor, - (pos & 0xFFFF), - component->y + ((type==BAGL_LABELINE)?-(baseline):valignment), - component->width - halignment, - component->height - ((type==BAGL_LABELINE)?0:valignment), - ellipsis_2_start, - (context_length - ((const void *)ellipsis_2_start-(const void *)context) ), - context_encoding); - } + if (ellipsis_2_start) { + // draw ellipsis + pos = bagl_draw_string( + component->font_id, + fgcolor, + bgcolor, + (pos & 0xFFFF), + component->y + ((type == BAGL_LABELINE) ? -(baseline) : valignment), + component->width - halignment, + component->height - (type == BAGL_LABELINE ? 0 : valignment), + "...", + 3, + context_encoding); + // draw the right part + bagl_draw_string( + component->font_id, + fgcolor, + bgcolor, + (pos & 0xFFFF), + component->y + ((type == BAGL_LABELINE) ? -(baseline) : valignment), + component->width - halignment, + component->height - ((type == BAGL_LABELINE) ? 0 : valignment), + ellipsis_2_start, + (context_length + - ((const void *) ellipsis_2_start - (const void *) context)), + context_encoding); + } #else - (void) pos; -#endif // HAVE_BAGL_ELLIPSIS - } - break; + (void) pos; +#endif // HAVE_BAGL_ELLIPSIS + } + break; #ifdef HAVE_BAGL_GLYPH_ARRAY - case BAGL_ICON: - // icon data follows are in the context - if (component->icon_id != 0) { - - // select the default or custom glyph array - if (context_encoding && G_glyph_array && G_glyph_count > 0) { - glyph = bagl_get_glyph(component->icon_id, G_glyph_array, G_glyph_count); - } - else { - glyph = bagl_get_glyph(component->icon_id, C_glyph_array, C_glyph_count); - } - - // 404 glyph not found - if (glyph == NULL) { - break; - } - - // color accounted as bytes in the context length - if (context_length) { - if ((1<bits_per_pixel)*4 != context_length) { - // invalid color count + case BAGL_ICON: + // icon data follows are in the context + if (component->icon_id != 0) { + // select the default or custom glyph array + if (context_encoding && G_glyph_array && G_glyph_count > 0) { + glyph = bagl_get_glyph(component->icon_id, G_glyph_array, G_glyph_count); + } + else { + glyph = bagl_get_glyph(component->icon_id, C_glyph_array, C_glyph_count); + } + + // 404 glyph not found + if (glyph == NULL) { + break; + } + + // color accounted as bytes in the context length + if (context_length) { + if ((1 << glyph->bits_per_pixel) * 4 != context_length) { + // invalid color count + break; + } + context_length /= 4; + } + // use default colors + if (!context_length || !context) { + context_length = 1 << (glyph->bits_per_pixel); + context = glyph->default_colors; + } + + // center glyph in rect + // draw the glyph from the bitmap using the context for colors + bagl_hal_draw_bitmap_within_rect( + component->x + (component->width / 2 - glyph->width / 2), + component->y + (component->height / 2 - glyph->height / 2), + glyph->width, + glyph->height, + context_length, + (unsigned int *) context, // Endianness remarkably ignored ! + glyph->bits_per_pixel, + glyph->bitmap, + glyph->bits_per_pixel * (glyph->width * glyph->height)); + } + else { + // context: [color_count*4 bytes (LE encoding)] + + unsigned int colors[4]; + unsigned int bpp = ((unsigned char *) context)[0]; + // no space to display that + if (bpp > 2) { + break; + } + unsigned int i = 1 << bpp; + while (i--) { + colors[i] = U4BE((unsigned char *) context, 1 + i * 4); + } + + // draw the glyph from the bitmap using the context for colors + bagl_hal_draw_bitmap_within_rect(component->x, + component->y, + component->width, + component->height, + 1 << bpp, + colors, + bpp, + ((unsigned char *) context) + 1 + (1 << bpp) * 4, + bpp * (component->width * component->height)); + } + break; +#endif // HAVE_BAGL_GLYPH_ARRAY + + case BAGL_CIRCLE: + // draw the circle (all 8 octants) + bagl_draw_circle_helper( + component->fgcolor, + component->x + component->radius, + component->y + component->radius, + component->radius, + 0xFF, + ((component->fill != BAGL_FILL && component->stroke < component->radius) + ? component->radius - component->stroke + : 0), + component->bgcolor); break; - } - context_length /= 4; - } - // use default colors - if (!context_length || !context) { - context_length = 1<<(glyph->bits_per_pixel); - context = glyph->default_colors; - } - - // center glyph in rect - // draw the glyph from the bitmap using the context for colors - bagl_hal_draw_bitmap_within_rect(component->x + (component->width / 2 - glyph->width / 2), - component->y + (component->height / 2 - glyph->height / 2), - glyph->width, - glyph->height, - context_length, - (unsigned int*)context, // Endianness remarkably ignored ! - glyph->bits_per_pixel, - glyph->bitmap, - glyph->bits_per_pixel*(glyph->width*glyph->height)); - } - else { - // context: [color_count*4 bytes (LE encoding)] - - unsigned int colors[4]; - unsigned int bpp = ((unsigned char*)context)[0]; - // no space to display that - if (bpp > 2) { - break; - } - unsigned int i=1<x, component->y, - component->width, component->height, - 1<width*component->height)); - } - break; -#endif // HAVE_BAGL_GLYPH_ARRAY - - case BAGL_CIRCLE: - // draw the circle (all 8 octants) - bagl_draw_circle_helper(component->fgcolor, - component->x+component->radius, component->y+component->radius, - component->radius, 0xFF, - ((component->fill != BAGL_FILL && component->stroke < component->radius)?component->radius-component->stroke:0), - component->bgcolor); - break; - - default: - break; - } + default: + break; + } } // -------------------------------------------------------------------------------------- -void bagl_draw_glyph(const bagl_component_t* component, const bagl_icon_details_t* icon_details) { - // no space to display that - if (icon_details->bpp > 2) { - return; - } - - /* - // take into account the remaining bits not byte aligned - unsigned int w = ((component->width*component->height*icon_details->bpp)/8); - if (w%8) { - w++; - } - */ - - // draw the glyph from the bitmap using the context for colors - bagl_hal_draw_bitmap_within_rect(component->x, - component->y, - icon_details->width, - icon_details->height, - 1<<(icon_details->bpp), +void bagl_draw_glyph(const bagl_component_t *component, const bagl_icon_details_t *icon_details) +{ + // no space to display that + if (icon_details->bpp > 2) { + return; + } + + /* + // take into account the remaining bits not byte aligned + unsigned int w = ((component->width*component->height*icon_details->bpp)/8); + if (w%8) { + w++; + } + */ + + // draw the glyph from the bitmap using the context for colors + bagl_hal_draw_bitmap_within_rect( + component->x, + component->y, + icon_details->width, + icon_details->height, + 1 << (icon_details->bpp), #ifdef DISPLAY_FLOWS - PIC(icon_details->colors), -#else //DISPLAY_FLOWS - (unsigned int*)PIC((unsigned int)icon_details->colors), -#endif //DISPLAY_FLOWS - icon_details->bpp, + PIC(icon_details->colors), +#else // DISPLAY_FLOWS + (unsigned int *) PIC((unsigned int) icon_details->colors), +#endif // DISPLAY_FLOWS + icon_details->bpp, #ifdef DISPLAY_FLOWS - PIC(icon_details->bitmap), -#else //DISPLAY_FLOWS - (unsigned char*)PIC((unsigned int)icon_details->bitmap), -#endif //DISPLAY_FLOWS - icon_details->bpp*(icon_details->width*icon_details->height)); + PIC(icon_details->bitmap), +#else // DISPLAY_FLOWS + (unsigned char *) PIC((unsigned int) icon_details->bitmap), +#endif // DISPLAY_FLOWS + icon_details->bpp * (icon_details->width * icon_details->height)); } - // -------------------------------------------------------------------------------------- -void bagl_draw(const bagl_component_t* component) { - // component without text - bagl_draw_with_context(component, NULL, 0, 0); +void bagl_draw(const bagl_component_t *component) +{ + // component without text + bagl_draw_with_context(component, NULL, 0, 0); } void bagl_init(void) { #ifdef HAVE_BAGL_GLYPH_ARRAY - G_glyph_array = NULL; - G_glyph_count = 0; -#endif // HAVE_BAGL_GLYPH_ARRAY + G_glyph_array = NULL; + G_glyph_count = 0; +#endif // HAVE_BAGL_GLYPH_ARRAY #if defined(HAVE_UNICODE_SUPPORT) - font_unicode = NULL; -#endif //defined(HAVE_UNICODE_SUPPORT) + font_unicode = NULL; +#endif // defined(HAVE_UNICODE_SUPPORT) } -#endif // HAVE_BAGL +#endif // HAVE_BAGL diff --git a/lib_bagl/src/bagl_animate.c b/lib_bagl/src/bagl_animate.c index 7c1e00212..5f6cde6e5 100644 --- a/lib_bagl/src/bagl_animate.c +++ b/lib_bagl/src/bagl_animate.c @@ -14,14 +14,14 @@ #define C_WHITE 0xFFFFFF // Font properties -#define FONT_REGULAR BAGL_FONT_OPEN_SANS_REGULAR_11px +#define FONT_REGULAR BAGL_FONT_OPEN_SANS_REGULAR_11px #define FONT_HEIGHT_PIXEL 11 -#define ENCODING BAGL_ENCODING_DEFAULT +#define ENCODING BAGL_ENCODING_DEFAULT // Margin on left and width of displayed text #define SCREEN_MARGIN_PIXEL 8 -#define LEFT_MARGIN 0 -#define BOX_WIDTH BAGL_WIDTH +#define LEFT_MARGIN 0 +#define BOX_WIDTH BAGL_WIDTH // Margin on top and height of the displayed text #define TOP_MARGIN ((BAGL_HEIGHT - FONT_HEIGHT_PIXEL) / 2) @@ -39,67 +39,70 @@ // Component used to display the label with the best properties const bagl_component_t component = { - BAGL_LABEL, - LABEL_ANIMATE_ID, - LEFT_MARGIN, // x - TOP_MARGIN, // y - BOX_WIDTH, // width - BOX_HEIGHT, // height - 0, 0, 0, // stroke, radius, fill - C_WHITE, // fg color - C_BLACK, // bg color - FONT_REGULAR, - 0, + BAGL_LABEL, + LABEL_ANIMATE_ID, + LEFT_MARGIN, // x + TOP_MARGIN, // y + BOX_WIDTH, // width + BOX_HEIGHT, // height + 0, + 0, + 0, // stroke, radius, fill + C_WHITE, // fg color + C_BLACK, // bg color + FONT_REGULAR, + 0, }; /* Reset values are depending on the animation type and compute at the context initialization */ -static void animation_reset(bagl_anim_t *anim) { - anim->cur_x = anim->reset_cur_x; - anim->cur_char_idx = anim->reset_cur_char_idx; - anim->cur_char_w = 0; - anim->cur_char_displayed_w = 0; +static void animation_reset(bagl_anim_t *anim) +{ + anim->cur_x = anim->reset_cur_x; + anim->cur_char_idx = anim->reset_cur_char_idx; + anim->cur_char_w = 0; + anim->cur_char_displayed_w = 0; } /* Process the different width properties of the label to animate. */ -static void animation_get_width_properties(bagl_anim_t *anim) { - const unsigned font_id = component.font_id; - const unsigned int idx = anim->cur_char_idx; - - // compute the remaining length in pixel to display - anim->rem_w = bagl_compute_line_width(font_id, 0, - anim->label + idx, - anim->len - idx, - ENCODING); - - // compute the current char width in pixel - anim->cur_char_w = bagl_compute_line_width(font_id, 0, - anim->label + idx, 1, - ENCODING); - - // comput the current char width already displayed in pixel - anim->cur_char_displayed_w = anim->cur_x - (anim->tot_w - anim->rem_w); +static void animation_get_width_properties(bagl_anim_t *anim) +{ + const unsigned font_id = component.font_id; + const unsigned int idx = anim->cur_char_idx; + + // compute the remaining length in pixel to display + anim->rem_w = bagl_compute_line_width(font_id, 0, anim->label + idx, anim->len - idx, ENCODING); + + // compute the current char width in pixel + anim->cur_char_w = bagl_compute_line_width(font_id, 0, anim->label + idx, 1, ENCODING); + + // comput the current char width already displayed in pixel + anim->cur_char_displayed_w = anim->cur_x - (anim->tot_w - anim->rem_w); } /* Print the label and refresh the screen */ -static void animation_draw(bagl_anim_t *anim) { - const unsigned font_id = component.font_id; - const char *start_label = anim->label + anim->cur_char_idx; - const uint16_t len = anim->len - anim->cur_char_idx; - - bagl_draw_bg(component.bgcolor); - - bagl_draw_string(font_id, - component.fgcolor, component.bgcolor, - component.x - anim->cur_char_displayed_w, component.y, - component.width, component.height, - start_label, len, - ENCODING); - - bagl_hal_draw_rect(component.bgcolor, 0, 0, - SCREEN_MARGIN_PIXEL, BAGL_HEIGHT); - bagl_hal_draw_rect(component.bgcolor, BAGL_WIDTH-SCREEN_MARGIN_PIXEL, 0, - SCREEN_MARGIN_PIXEL, BAGL_HEIGHT); +static void animation_draw(bagl_anim_t *anim) +{ + const unsigned font_id = component.font_id; + const char *start_label = anim->label + anim->cur_char_idx; + const uint16_t len = anim->len - anim->cur_char_idx; + + bagl_draw_bg(component.bgcolor); + + bagl_draw_string(font_id, + component.fgcolor, + component.bgcolor, + component.x - anim->cur_char_displayed_w, + component.y, + component.width, + component.height, + start_label, + len, + ENCODING); + + bagl_hal_draw_rect(component.bgcolor, 0, 0, SCREEN_MARGIN_PIXEL, BAGL_HEIGHT); + bagl_hal_draw_rect( + component.bgcolor, BAGL_WIDTH - SCREEN_MARGIN_PIXEL, 0, SCREEN_MARGIN_PIXEL, BAGL_HEIGHT); } /** @@ -107,244 +110,242 @@ static void animation_draw(bagl_anim_t *anim) { */ typedef enum classic_state_e { - STATE_FROM_RIGHT_TO_LEFT, - STATE_FROM_LEFT_TO_RIGHT, - STATE_LEFT_PAUSE, - STATE_RIGHT_PAUSE, - STATE_END, + STATE_FROM_RIGHT_TO_LEFT, + STATE_FROM_LEFT_TO_RIGHT, + STATE_LEFT_PAUSE, + STATE_RIGHT_PAUSE, + STATE_END, } classic_state_t; -static void classic_right_to_left(bagl_anim_t *anim) { - /* Char has been entirely displayed ? */ - if (anim->cur_char_displayed_w < anim->cur_char_w) { +static void classic_right_to_left(bagl_anim_t *anim) +{ + /* Char has been entirely displayed ? */ + if (anim->cur_char_displayed_w < anim->cur_char_w) { + ++anim->cur_x; + return; + } + + /* Start to display the next char of the text */ + ++anim->cur_char_idx; ++anim->cur_x; - return; - } - - /* Start to display the next char of the text */ - ++anim->cur_char_idx; - ++anim->cur_x; - - /* Left border has been reached ? [<------ ] */ - if (anim->rem_w - anim->cur_char_displayed_w <= component.width) { - anim->cur_x = anim->tot_w - anim->rem_w + anim->cur_char_displayed_w; - anim->classic.state = STATE_LEFT_PAUSE; - } + + /* Left border has been reached ? [<------ ] */ + if (anim->rem_w - anim->cur_char_displayed_w <= component.width) { + anim->cur_x = anim->tot_w - anim->rem_w + anim->cur_char_displayed_w; + anim->classic.state = STATE_LEFT_PAUSE; + } } -static void classic_left_to_right(bagl_anim_t *anim) { - /* Char has been entirely displayed ? */ - if (anim->cur_char_displayed_w >= anim->cur_char_w) { - --anim->cur_char_idx; - } - - /* Right border has been reached ? [ ------>] */ - if (anim->cur_x == 0 && anim->rem_w == anim->tot_w) { - anim->cur_char_idx = 0; - anim->cur_x = 0; - anim->classic.state = STATE_FROM_RIGHT_TO_LEFT; - return; - } - - --anim->cur_x; +static void classic_left_to_right(bagl_anim_t *anim) +{ + /* Char has been entirely displayed ? */ + if (anim->cur_char_displayed_w >= anim->cur_char_w) { + --anim->cur_char_idx; + } + + /* Right border has been reached ? [ ------>] */ + if (anim->cur_x == 0 && anim->rem_w == anim->tot_w) { + anim->cur_char_idx = 0; + anim->cur_x = 0; + anim->classic.state = STATE_FROM_RIGHT_TO_LEFT; + return; + } + + --anim->cur_x; } // A pause in classic animation is based on a number of ticker calls. -static void classic_pause(bagl_anim_t *anim, - classic_state_t next_state) { - ++anim->classic.nr_ticker_pause; - if (anim->classic.nr_ticker_pause == TICKER_PAUSE) { - anim->classic.state = next_state; - anim->classic.nr_ticker_pause = 0; - } +static void classic_pause(bagl_anim_t *anim, classic_state_t next_state) +{ + ++anim->classic.nr_ticker_pause; + if (anim->classic.nr_ticker_pause == TICKER_PAUSE) { + anim->classic.state = next_state; + anim->classic.nr_ticker_pause = 0; + } } // Statemachine for the classic animation -static void classic_step(bagl_anim_t *anim) { - switch (anim->classic.state) { - case STATE_FROM_RIGHT_TO_LEFT: - classic_right_to_left(anim); - break; - case STATE_FROM_LEFT_TO_RIGHT: - classic_left_to_right(anim); - break; - case STATE_LEFT_PAUSE: - classic_pause(anim, STATE_FROM_LEFT_TO_RIGHT); - break; - case STATE_RIGHT_PAUSE: - classic_pause(anim, STATE_FROM_RIGHT_TO_LEFT); - break; - case STATE_END: - break; - } +static void classic_step(bagl_anim_t *anim) +{ + switch (anim->classic.state) { + case STATE_FROM_RIGHT_TO_LEFT: + classic_right_to_left(anim); + break; + case STATE_FROM_LEFT_TO_RIGHT: + classic_left_to_right(anim); + break; + case STATE_LEFT_PAUSE: + classic_pause(anim, STATE_FROM_LEFT_TO_RIGHT); + break; + case STATE_RIGHT_PAUSE: + classic_pause(anim, STATE_FROM_RIGHT_TO_LEFT); + break; + case STATE_END: + break; + } } -static void fill_label_with_space(char *label, - uint16_t from, - uint16_t n) { - for (uint16_t i = 0; i < n; ++i) { - label[i + from] = ' '; - } +static void fill_label_with_space(char *label, uint16_t from, uint16_t n) +{ + for (uint16_t i = 0; i < n; ++i) { + label[i + from] = ' '; + } } -static void classic_init(bagl_anim_t *anim, - const unsigned char *label, - size_t len) { - // Add auto padding spaces - uint16_t nr_space = (MAX_LABEL_SIZE - len) / 2; - if (nr_space > NR_MAX_SPACE_PADDING) { - nr_space = NR_MAX_SPACE_PADDING; - } - - /* <-- nr_space --><-- len --><-- nr_space --> - [ ][ label ][ ] */ - anim->len = len + nr_space * 2; - fill_label_with_space(anim->label, 0, nr_space); - memcpy(anim->label + nr_space, label, len); - fill_label_with_space(anim->label, len + nr_space, nr_space); - - // compute once the total width in pixel of the label - anim->tot_w = bagl_compute_line_width(component.font_id, 0, - anim->label, anim->len, ENCODING); - anim->classic.state = STATE_FROM_RIGHT_TO_LEFT; - anim->reset_cur_x = 0; - anim->reset_cur_char_idx = 0; - animation_reset(anim); +static void classic_init(bagl_anim_t *anim, const unsigned char *label, size_t len) +{ + // Add auto padding spaces + uint16_t nr_space = (MAX_LABEL_SIZE - len) / 2; + if (nr_space > NR_MAX_SPACE_PADDING) { + nr_space = NR_MAX_SPACE_PADDING; + } + + /* <-- nr_space --><-- len --><-- nr_space --> + [ ][ label ][ ] */ + anim->len = len + nr_space * 2; + fill_label_with_space(anim->label, 0, nr_space); + memcpy(anim->label + nr_space, label, len); + fill_label_with_space(anim->label, len + nr_space, nr_space); + + // compute once the total width in pixel of the label + anim->tot_w = bagl_compute_line_width(component.font_id, 0, anim->label, anim->len, ENCODING); + anim->classic.state = STATE_FROM_RIGHT_TO_LEFT; + anim->reset_cur_x = 0; + anim->reset_cur_char_idx = 0; + animation_reset(anim); } /** * Circle common */ -static void circle_common_init(bagl_anim_t *anim, - const unsigned char *label, - size_t len) { - anim->circle.char_idx_limit = len - 1 + sizeof(DELIMITER) - 1; - anim->len = 0; - - /* <-- len --><-- len(DELIMITER) --><-- len --> - [ label ][ ][ label ] */ - - while ((anim->len+len + sizeof(DELIMITER)) < MAX_LABEL_SIZE) { - snprintf((char*)(anim->label+anim->len), sizeof(anim->label)-anim->len, - "%s%s", label, DELIMITER); - anim->len += len + sizeof(DELIMITER); - } - anim->len -= sizeof(DELIMITER); - - // compute once the total width in pixel of the label - anim->tot_w = bagl_compute_line_width(component.font_id, 0, - anim->label, - anim->len, - ENCODING); +static void circle_common_init(bagl_anim_t *anim, const unsigned char *label, size_t len) +{ + anim->circle.char_idx_limit = len - 1 + sizeof(DELIMITER) - 1; + anim->len = 0; + + /* <-- len --><-- len(DELIMITER) --><-- len --> + [ label ][ ][ label ] */ + + while ((anim->len + len + sizeof(DELIMITER)) < MAX_LABEL_SIZE) { + snprintf((char *) (anim->label + anim->len), + sizeof(anim->label) - anim->len, + "%s%s", + label, + DELIMITER); + anim->len += len + sizeof(DELIMITER); + } + anim->len -= sizeof(DELIMITER); + + // compute once the total width in pixel of the label + anim->tot_w = bagl_compute_line_width(component.font_id, 0, anim->label, anim->len, ENCODING); } /** * Circle right to left animation. */ -static void circle_rl_step(bagl_anim_t *anim) { - /* Char has been entirely displayed ? */ - if (anim->cur_char_displayed_w < anim->cur_char_w) { - ++anim->cur_x; - return; - } +static void circle_rl_step(bagl_anim_t *anim) +{ + /* Char has been entirely displayed ? */ + if (anim->cur_char_displayed_w < anim->cur_char_w) { + ++anim->cur_x; + return; + } - /* Reset when needed */ - if (anim->cur_char_idx == anim->circle.char_idx_limit) { - animation_reset(anim); - ++anim->cur_x; - return; - } + /* Reset when needed */ + if (anim->cur_char_idx == anim->circle.char_idx_limit) { + animation_reset(anim); + ++anim->cur_x; + return; + } - /* Start to display the next char of the text */ - ++anim->cur_char_idx; - ++anim->cur_x; + /* Start to display the next char of the text */ + ++anim->cur_char_idx; + ++anim->cur_x; } -static void circle_rl_init(bagl_anim_t *anim, - const unsigned char *label, - size_t len) { - circle_common_init(anim, label, len); - anim->reset_cur_char_idx = 0; - anim->reset_cur_x = 0; - animation_reset(anim); +static void circle_rl_init(bagl_anim_t *anim, const unsigned char *label, size_t len) +{ + circle_common_init(anim, label, len); + anim->reset_cur_char_idx = 0; + anim->reset_cur_x = 0; + animation_reset(anim); } /** * Circle left to right animation. */ -static void circle_lr_step(bagl_anim_t *anim) { - - /* Char has been entirely displayed ? */ - if (anim->cur_char_displayed_w >= anim->cur_char_w) { - if (anim->cur_char_idx == 0) { - animation_reset(anim); - ++anim->cur_x; - return; +static void circle_lr_step(bagl_anim_t *anim) +{ + /* Char has been entirely displayed ? */ + if (anim->cur_char_displayed_w >= anim->cur_char_w) { + if (anim->cur_char_idx == 0) { + animation_reset(anim); + ++anim->cur_x; + return; + } + --anim->cur_char_idx; } - --anim->cur_char_idx; - } - /* Display next pixel */ - --anim->cur_x; + /* Display next pixel */ + --anim->cur_x; } -static void circle_lr_init(bagl_anim_t *anim, - const unsigned char *label, - size_t len) { - circle_common_init(anim, label, len); - // reset values are processed to have a transparent animation for the user - anim->reset_cur_x = bagl_compute_line_width(component.font_id, 0, - anim->label, - anim->circle.char_idx_limit, - ENCODING); - anim->reset_cur_char_idx = anim->circle.char_idx_limit; - animation_reset(anim); +static void circle_lr_init(bagl_anim_t *anim, const unsigned char *label, size_t len) +{ + circle_common_init(anim, label, len); + // reset values are processed to have a transparent animation for the user + anim->reset_cur_x = bagl_compute_line_width( + component.font_id, 0, anim->label, anim->circle.char_idx_limit, ENCODING); + anim->reset_cur_char_idx = anim->circle.char_idx_limit; + animation_reset(anim); } -void bagl_animation_init(bagl_anim_t *anim, - anim_type_t type, +void bagl_animation_init(bagl_anim_t *anim, + anim_type_t type, const unsigned char *label, - size_t len) { - anim->type = type; - memset(anim->label, 0, MAX_LABEL_SIZE); - anim->max_char_w = bagl_compute_line_width(component.font_id, 0, "W", 1, ENCODING) + 1; - - switch (anim->type) { - case ANIMATION_TYPE_CLASSIC: - classic_init(anim, label, len); - break; - case ANIMATION_TYPE_CIRCLE_RL: - circle_rl_init(anim, label, len); - break; - case ANIMATION_TYPE_CIRCLE_LR: - circle_lr_init(anim, label, len); - break; - case ANIMATION_TYPE_END: - break; - }; + size_t len) +{ + anim->type = type; + memset(anim->label, 0, MAX_LABEL_SIZE); + anim->max_char_w = bagl_compute_line_width(component.font_id, 0, "W", 1, ENCODING) + 1; + + switch (anim->type) { + case ANIMATION_TYPE_CLASSIC: + classic_init(anim, label, len); + break; + case ANIMATION_TYPE_CIRCLE_RL: + circle_rl_init(anim, label, len); + break; + case ANIMATION_TYPE_CIRCLE_LR: + circle_lr_init(anim, label, len); + break; + case ANIMATION_TYPE_END: + break; + }; } -void bagl_animation_step(bagl_anim_t *anim) { - animation_get_width_properties(anim); - animation_draw(anim); - screen_update(); - - switch (anim->type) { - case ANIMATION_TYPE_CLASSIC: - classic_step(anim); - break; - case ANIMATION_TYPE_CIRCLE_RL: - circle_rl_step(anim); - break; - case ANIMATION_TYPE_CIRCLE_LR: - circle_lr_step(anim); - break; - case ANIMATION_TYPE_END: - break; - }; +void bagl_animation_step(bagl_anim_t *anim) +{ + animation_get_width_properties(anim); + animation_draw(anim); + screen_update(); + + switch (anim->type) { + case ANIMATION_TYPE_CLASSIC: + classic_step(anim); + break; + case ANIMATION_TYPE_CIRCLE_RL: + circle_rl_step(anim); + break; + case ANIMATION_TYPE_CIRCLE_LR: + circle_lr_step(anim); + break; + case ANIMATION_TYPE_END: + break; + }; } #endif /* HAVE_SE_SCREEN */ diff --git a/lib_bagl/src/bagl_fonts.c b/lib_bagl/src/bagl_fonts.c index 71a6d2101..d12f3e61d 100644 --- a/lib_bagl/src/bagl_fonts.c +++ b/lib_bagl/src/bagl_fonts.c @@ -1,20 +1,20 @@ /******************************************************************************* -* Ledger Nano S - Secure firmware -* (c) 2022 Ledger -* -* Licensed under the Apache License, Version 2.0 (the "License"); -* you may not use this file except in compliance with the License. -* You may obtain a copy of the License at -* -* http://www.apache.org/licenses/LICENSE-2.0 -* -* Unless required by applicable law or agreed to in writing, software -* distributed under the License is distributed on an "AS IS" BASIS, -* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -* See the License for the specific language governing permissions and -* limitations under the License. -********************************************************************************/ + * Ledger Nano S - Secure firmware + * (c) 2022 Ledger + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT 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 "string.h" #include "bagl.h" @@ -28,25 +28,26 @@ #include "bagl_font_rom.inc" -const bagl_font_t* const C_bagl_fonts[] = { +const bagl_font_t *const C_bagl_fonts[] = { #include "bagl_font_rom_struct.inc" - }; -const unsigned int C_bagl_fonts_count = sizeof(C_bagl_fonts)/sizeof(C_bagl_fonts[0]); +const unsigned int C_bagl_fonts_count = sizeof(C_bagl_fonts) / sizeof(C_bagl_fonts[0]); #if defined(HAVE_UNICODE_SUPPORT) #if !defined(HAVE_LANGUAGE_PACK) -const bagl_font_unicode_t* const C_bagl_fonts_unicode[] = { +const bagl_font_unicode_t *const C_bagl_fonts_unicode[] = { #include "bagl_font_unicode_rom_struct.inc" }; // All Unicode fonts MUST have the same number of characters! -const unsigned int C_unicode_characters_count = (sizeof(charactersOPEN_SANS_REGULAR_11PX_UNICODE)/sizeof(charactersOPEN_SANS_REGULAR_11PX_UNICODE[0])); +const unsigned int C_unicode_characters_count + = (sizeof(charactersOPEN_SANS_REGULAR_11PX_UNICODE) + / sizeof(charactersOPEN_SANS_REGULAR_11PX_UNICODE[0])); -#endif //!defined(HAVE_LANGUAGE_PACK) -#endif //defined(HAVE_UNICODE_SUPPORT) +#endif //! defined(HAVE_LANGUAGE_PACK) +#endif // defined(HAVE_UNICODE_SUPPORT) diff --git a/lib_bagl/src/bagl_glyphs.c b/lib_bagl/src/bagl_glyphs.c index 90d8e1773..06e8d4d0d 100644 --- a/lib_bagl/src/bagl_glyphs.c +++ b/lib_bagl/src/bagl_glyphs.c @@ -1,2474 +1,2382 @@ /******************************************************************************* -* Ledger Blue - Non secure firmware -* (c) 2016 Ledger -* -* Licensed under the Apache License, Version 2.0 (the "License"); -* you may not use this file except in compliance with the License. -* You may obtain a copy of the License at -* -* http://www.apache.org/licenses/LICENSE-2.0 -* -* Unless required by applicable law or agreed to in writing, software -* distributed under the License is distributed on an "AS IS" BASIS, -* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -* See the License for the specific language governing permissions and -* limitations under the License. -********************************************************************************/ + * Ledger Blue - Non secure firmware + * (c) 2016 Ledger + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT 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 "string.h" #include "bagl.h" #ifdef HAVE_BAGL_GLYPH_ARRAY unsigned int const C_logo_ledger_colors[] = { - 0x00aaabae, - 0x00585b65, - 0x00d3d4d5, - 0x00e2e2e3, - 0x008b8d92, - 0x00cacbce, - 0x00f9f9f9, - 0x00333746, - 0x0074767e, - 0x00eeeeee, - 0x009d9fa4, - 0x00b6b7bb, - 0x00f6f6f7, - 0x00a4a5ab, - 0x00484c57, - 0x00bfbfc3, + 0x00aaabae, + 0x00585b65, + 0x00d3d4d5, + 0x00e2e2e3, + 0x008b8d92, + 0x00cacbce, + 0x00f9f9f9, + 0x00333746, + 0x0074767e, + 0x00eeeeee, + 0x009d9fa4, + 0x00b6b7bb, + 0x00f6f6f7, + 0x00a4a5ab, + 0x00484c57, + 0x00bfbfc3, }; unsigned char const C_logo_ledger_bitmap[] = { - 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x85, 0x7e, - 0x77, 0x77, 0x63, 0x66, 0x66, 0x56, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, - 0x77, 0x77, 0xe7, 0xb8, 0x6c, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, - 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x36, - 0x78, 0x77, 0x77, 0x77, 0x37, 0x66, 0x66, 0x66, 0x75, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, - 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x17, 0x65, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, - 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, - 0x66, 0x26, 0x7e, 0x77, 0x77, 0x77, 0x77, 0x63, 0x66, 0x66, 0x56, 0x77, 0x77, 0x77, 0x77, 0x77, - 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x6b, 0x66, 0x66, 0x66, 0x66, 0x66, - 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, - 0x66, 0x66, 0x66, 0x96, 0x7e, 0x77, 0x77, 0x77, 0x77, 0x37, 0x66, 0x66, 0x66, 0x75, 0x77, 0x77, - 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x62, 0x66, 0x66, - 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, - 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x74, 0x77, 0x77, 0x77, 0x77, 0x77, 0x63, 0x66, 0x66, 0x56, - 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x17, - 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, - 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x79, 0x77, 0x77, 0x77, 0x77, 0x77, 0x37, 0x66, - 0x66, 0x66, 0x75, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, - 0x77, 0x77, 0xf7, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, - 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x06, 0x77, 0x77, 0x77, 0x77, 0x77, - 0x77, 0x63, 0x66, 0x66, 0x56, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, - 0x77, 0x77, 0x77, 0x77, 0x77, 0x64, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, - 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x74, 0x77, 0x77, - 0x77, 0x77, 0x77, 0x37, 0x66, 0x66, 0x66, 0x75, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, - 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x17, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, - 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x86, - 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x63, 0x66, 0x66, 0x56, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, - 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x61, 0x66, 0x66, 0x66, 0x66, 0x66, - 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, - 0x66, 0x66, 0x78, 0x77, 0x77, 0x77, 0x77, 0x77, 0x37, 0x66, 0x66, 0x66, 0x75, 0x77, 0x77, 0x77, - 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x17, 0x66, 0x66, 0x66, - 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, - 0x66, 0x66, 0x66, 0x66, 0x86, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x63, 0x66, 0x66, 0x56, 0x77, - 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x61, - 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, - 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x78, 0x77, 0x77, 0x77, 0x77, 0x77, 0x37, 0x66, 0x66, - 0x66, 0x75, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, - 0x77, 0x17, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, - 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0xa6, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, - 0x69, 0x66, 0x66, 0x56, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, - 0x77, 0x77, 0x77, 0x77, 0x61, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, - 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, - 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x75, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, - 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x17, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, - 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, - 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x56, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, - 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x61, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, - 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, - 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x75, 0x77, 0x77, 0x77, 0x77, - 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x17, 0x66, 0x66, 0x66, 0x66, - 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, - 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x56, 0x77, 0x77, - 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x61, 0x66, - 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, - 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, - 0x75, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, - 0x17, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, - 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, - 0x66, 0x66, 0x56, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, - 0x77, 0x77, 0x77, 0x61, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, - 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, - 0x66, 0x66, 0x66, 0x66, 0x66, 0x75, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, - 0x77, 0x77, 0x77, 0x77, 0x77, 0x17, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, - 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0xd6, 0x88, 0x88, - 0x88, 0x88, 0x88, 0x88, 0x69, 0x66, 0x66, 0x56, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, - 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x61, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, - 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, - 0x78, 0x77, 0x77, 0x77, 0x77, 0x77, 0x37, 0x66, 0x66, 0x66, 0x75, 0x77, 0x77, 0x77, 0x77, 0x77, - 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x17, 0x66, 0x66, 0x66, 0x66, 0x66, - 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, - 0x66, 0x66, 0x86, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x63, 0x66, 0x66, 0x56, 0x77, 0x77, 0x77, - 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x61, 0x66, 0x66, - 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, - 0x66, 0x66, 0x66, 0x66, 0x66, 0x78, 0x77, 0x77, 0x77, 0x77, 0x77, 0x37, 0x66, 0x66, 0x66, 0x75, - 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x17, - 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, - 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x86, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x63, 0x66, - 0x66, 0x56, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, - 0x77, 0x77, 0x61, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, - 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x78, 0x77, 0x77, 0x77, 0x77, 0x77, - 0x37, 0x66, 0x66, 0x66, 0x75, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, - 0x77, 0x77, 0x77, 0x77, 0x17, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, - 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x86, 0x77, 0x77, 0x77, - 0x77, 0x77, 0x77, 0x63, 0x66, 0x66, 0x56, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, - 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x61, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, - 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x78, - 0x77, 0x77, 0x77, 0x77, 0x77, 0x37, 0x66, 0x66, 0x66, 0x75, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, - 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x17, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, - 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, - 0x66, 0x86, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x63, 0x66, 0x66, 0x56, 0x77, 0x77, 0x77, 0x77, - 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x61, 0x66, 0x66, 0x66, - 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, - 0x66, 0x66, 0x66, 0x66, 0x78, 0x77, 0x77, 0x77, 0x77, 0x77, 0x37, 0x66, 0x66, 0x66, 0x75, 0x77, - 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x17, 0x66, - 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, - 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x86, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x63, 0x66, 0x66, - 0x56, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, - 0x77, 0x61, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, - 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x78, 0x77, 0x77, 0x77, 0x77, 0x77, 0x37, - 0x66, 0x66, 0x66, 0x75, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, - 0x77, 0x77, 0x77, 0x17, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, - 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x86, 0x77, 0x77, 0x77, 0x77, - 0x77, 0x77, 0x63, 0x66, 0x66, 0x56, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, - 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x61, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, - 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x99, 0x99, - 0x99, 0x99, 0x99, 0x99, 0xc9, 0x66, 0x66, 0x66, 0x9c, 0x99, 0x99, 0x99, 0x99, 0x99, 0x99, 0x99, - 0x99, 0x99, 0x99, 0x99, 0x99, 0x99, 0x99, 0x99, 0x99, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, - 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, - 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, - 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, - 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, - 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, - 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, - 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, - 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, - 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, - 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, - 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, - 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, - 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, - 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, - 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, - 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, - 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, - 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, - 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, - 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x56, - 0xbb, 0xbb, 0xbb, 0xbb, 0xbb, 0xbb, 0x69, 0x66, 0x66, 0x96, 0xbb, 0xbb, 0xbb, 0xbb, 0xbb, 0xbb, - 0x63, 0x66, 0x66, 0x66, 0xbf, 0xbb, 0xbb, 0xbb, 0xbb, 0xbb, 0x6f, 0x66, 0x66, 0x66, 0x66, 0x66, - 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, - 0x66, 0x66, 0x78, 0x77, 0x77, 0x77, 0x77, 0x77, 0x37, 0x66, 0x66, 0x66, 0x75, 0x77, 0x77, 0x77, - 0x77, 0x77, 0xa7, 0x66, 0x66, 0x66, 0xe6, 0x77, 0x77, 0x77, 0x77, 0x77, 0x17, 0x66, 0x66, 0x66, - 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, - 0x66, 0x66, 0x66, 0x66, 0x86, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x63, 0x66, 0x66, 0x56, 0x77, - 0x77, 0x77, 0x77, 0x77, 0x77, 0x6a, 0x66, 0x66, 0x66, 0x7e, 0x77, 0x77, 0x77, 0x77, 0x77, 0x61, - 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, - 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x78, 0x77, 0x77, 0x77, 0x77, 0x77, 0x37, 0x66, 0x66, - 0x66, 0x75, 0x77, 0x77, 0x77, 0x77, 0x77, 0xa7, 0x66, 0x66, 0x66, 0xe6, 0x77, 0x77, 0x77, 0x77, - 0x77, 0x17, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, - 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x86, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, - 0x63, 0x66, 0x66, 0x56, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x6a, 0x66, 0x66, 0x66, 0x7e, 0x77, - 0x77, 0x77, 0x77, 0x77, 0x61, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, - 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x74, 0x77, 0x77, 0x77, - 0x77, 0x77, 0x37, 0x66, 0x66, 0x66, 0x75, 0x77, 0x77, 0x77, 0x77, 0x77, 0xa7, 0x66, 0x66, 0x66, - 0xe6, 0x77, 0x77, 0x77, 0x77, 0x77, 0x17, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, - 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0xa6, 0x77, - 0x77, 0x77, 0x77, 0x77, 0x77, 0x63, 0x66, 0x66, 0x56, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x6a, - 0x66, 0x66, 0x66, 0x7e, 0x77, 0x77, 0x77, 0x77, 0x77, 0x68, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, - 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, - 0x66, 0x72, 0x77, 0x77, 0x77, 0x77, 0x77, 0x37, 0x66, 0x66, 0x66, 0x75, 0x77, 0x77, 0x77, 0x77, - 0x77, 0xa7, 0x66, 0x66, 0x66, 0xe6, 0x77, 0x77, 0x77, 0x77, 0x77, 0x07, 0x66, 0x66, 0x66, 0x66, - 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, - 0x66, 0x66, 0x66, 0x66, 0x71, 0x77, 0x77, 0x77, 0x77, 0x77, 0x63, 0x66, 0x66, 0x56, 0x77, 0x77, - 0x77, 0x77, 0x77, 0x77, 0x6a, 0x66, 0x66, 0x66, 0x7e, 0x77, 0x77, 0x77, 0x77, 0x77, 0x69, 0x66, - 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, - 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x56, 0x77, 0x77, 0x77, 0x77, 0x77, 0x37, 0x66, 0x66, 0x66, - 0x75, 0x77, 0x77, 0x77, 0x77, 0x77, 0xa7, 0x66, 0x66, 0x66, 0xe6, 0x77, 0x77, 0x77, 0x77, 0x77, - 0x6a, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, - 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0xa6, 0x77, 0x77, 0x77, 0x77, 0x77, 0x63, - 0x66, 0x66, 0x56, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x6a, 0x66, 0x66, 0x66, 0x7e, 0x77, 0x77, - 0x77, 0x77, 0xc8, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, - 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x06, 0x77, 0x77, 0x77, - 0x77, 0x37, 0x66, 0x66, 0x66, 0x75, 0x77, 0x77, 0x77, 0x77, 0x77, 0xa7, 0x66, 0x66, 0x66, 0xe6, - 0x77, 0x77, 0x77, 0x77, 0xc4, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, - 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x36, - 0x78, 0x77, 0x77, 0x77, 0x63, 0x66, 0x66, 0x56, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x6a, 0x66, - 0x66, 0x66, 0x7e, 0x77, 0x77, 0x17, 0x65, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, - 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, - 0x66, 0x66, 0x66, 0xf9, 0x00, 0x00, 0x90, 0x66, 0x66, 0x66, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x20, 0x66, 0x66, 0x66, 0xb6, 0x00, 0x00, 0x3f, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, - 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, - 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, - 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, - 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, - 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, - 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, - 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, - 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, - 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, - 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, - 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, - 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, - 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, - 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, - 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, - 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, - 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, - 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, - 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, - 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, - 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, - 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, - 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, - 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, - 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, - 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, - 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, - 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, - 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, - 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, - 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, - 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, - 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, - 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, - 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, - 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, - 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x36, 0xf8, 0x66, 0x66, 0x66, 0x66, - 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, - 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, - 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x72, 0x60, 0x66, - 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, - 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x76, 0x68, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, - 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x26, - 0x07, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, - 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x87, 0x66, 0x66, 0x66, 0x66, 0x66, - 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, - 0x66, 0x66, 0x72, 0x60, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, - 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x76, 0x68, 0x66, 0x66, - 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, - 0x66, 0x66, 0x66, 0x66, 0x26, 0x07, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, - 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x87, - 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, - 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x72, 0x60, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, - 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, - 0x66, 0x76, 0x68, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, - 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x26, 0x07, 0x66, 0x66, 0x66, 0x66, 0x66, - 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, - 0x66, 0x66, 0x66, 0x66, 0x87, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, - 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x72, 0x60, 0x66, 0x66, - 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, - 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x76, 0x68, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, - 0x66, 0x26, 0x22, 0x62, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x29, 0x22, 0x62, 0x66, 0x26, 0x07, - 0x66, 0x66, 0x66, 0x36, 0x22, 0x22, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x23, 0x22, 0x69, - 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x29, 0x22, 0x62, 0x87, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, - 0x66, 0x66, 0x36, 0x74, 0x77, 0x77, 0x0e, 0x69, 0x66, 0x66, 0x66, 0x26, 0x74, 0x77, 0x77, 0x47, - 0x63, 0x72, 0x60, 0x66, 0x66, 0x1f, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x62, 0x66, 0x49, 0x7e, - 0x77, 0x77, 0x34, 0x66, 0x66, 0x06, 0x67, 0x96, 0x74, 0x77, 0x77, 0x72, 0x68, 0x66, 0x66, 0x66, - 0x66, 0x66, 0x66, 0x66, 0xb6, 0x77, 0x04, 0x52, 0x10, 0x17, 0x63, 0x66, 0x66, 0xa6, 0x77, 0x08, - 0xff, 0x40, 0xe7, 0x2f, 0x07, 0x66, 0x66, 0x74, 0xf1, 0x22, 0xf2, 0x71, 0xa7, 0x00, 0x90, 0x66, - 0xe2, 0x87, 0x50, 0x02, 0x78, 0xfe, 0x66, 0x66, 0x70, 0x39, 0x7e, 0x04, 0x00, 0x64, 0x87, 0x66, - 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0xb6, 0x87, 0x63, 0x66, 0x66, 0x46, 0x17, 0x69, 0x66, 0xa6, - 0xe7, 0x62, 0x66, 0x66, 0x36, 0x78, 0x7b, 0x60, 0x66, 0x7a, 0x64, 0x66, 0x66, 0x66, 0x74, 0x6a, - 0x66, 0x66, 0x73, 0x5e, 0x66, 0x66, 0x66, 0x7f, 0x37, 0x66, 0x06, 0x27, 0xe8, 0x63, 0x66, 0x66, - 0x76, 0x68, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x26, 0xe7, 0x69, 0x66, 0x66, 0x66, 0x46, 0xa7, - 0x66, 0x26, 0xe7, 0x63, 0x66, 0x66, 0x66, 0x66, 0x78, 0x07, 0x66, 0x73, 0x61, 0x66, 0x66, 0x66, - 0x66, 0x71, 0x63, 0x66, 0xe9, 0x27, 0x66, 0x66, 0x66, 0x66, 0x7b, 0x68, 0x66, 0x70, 0xe8, 0x63, - 0x66, 0x66, 0x66, 0x87, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x78, 0x62, 0x66, 0x66, 0x66, - 0x66, 0x79, 0x97, 0x66, 0x74, 0x6b, 0x66, 0x66, 0x66, 0x66, 0x26, 0x77, 0x60, 0x06, 0xb7, 0x66, - 0x66, 0x66, 0x66, 0xb6, 0xb7, 0x66, 0x06, 0x07, 0x66, 0x66, 0x66, 0x66, 0x66, 0x78, 0x65, 0x06, - 0x77, 0x6b, 0x66, 0x66, 0x66, 0x76, 0x68, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x73, 0x68, 0x66, - 0x66, 0x66, 0x66, 0x66, 0x74, 0x6f, 0x79, 0x9e, 0x66, 0x66, 0x66, 0x66, 0x66, 0x86, 0x07, 0x66, - 0x78, 0x62, 0x66, 0x66, 0x66, 0x66, 0x72, 0x64, 0x66, 0x7e, 0x69, 0x66, 0x66, 0x66, 0x66, 0xf6, - 0x47, 0x66, 0x70, 0x6e, 0x66, 0x66, 0x66, 0x66, 0x87, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x06, - 0x07, 0x66, 0x66, 0x66, 0x66, 0x66, 0xb6, 0xa7, 0x56, 0x47, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, - 0x7a, 0x60, 0x86, 0x27, 0x66, 0x66, 0x66, 0x66, 0x26, 0x87, 0x66, 0x72, 0x68, 0x66, 0x66, 0x66, - 0x66, 0x66, 0x73, 0x68, 0x06, 0x47, 0x66, 0x66, 0x66, 0x66, 0x76, 0x68, 0x66, 0x66, 0x66, 0x66, - 0x66, 0x66, 0x78, 0x62, 0x66, 0x66, 0x66, 0x66, 0x66, 0x72, 0x68, 0x70, 0x60, 0x66, 0x66, 0x66, - 0x66, 0x66, 0xb6, 0x07, 0x66, 0x74, 0x62, 0x66, 0x66, 0x66, 0x66, 0x72, 0x6a, 0x06, 0x07, 0x66, - 0x66, 0x66, 0x66, 0x66, 0x66, 0x77, 0x66, 0x70, 0x60, 0x66, 0x66, 0x66, 0x66, 0x87, 0x66, 0x66, - 0x66, 0x66, 0x66, 0x66, 0xe6, 0x37, 0x66, 0x66, 0x66, 0x66, 0x66, 0x26, 0x87, 0x46, 0x27, 0x66, - 0x66, 0x66, 0x66, 0x66, 0x66, 0x72, 0x60, 0xb6, 0xa7, 0x66, 0x66, 0x66, 0x66, 0xa6, 0xf7, 0x66, - 0x74, 0x6f, 0x66, 0x66, 0x66, 0x66, 0x66, 0x76, 0x67, 0x06, 0x27, 0x66, 0x66, 0x66, 0x66, 0x76, - 0x68, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x68, - 0x78, 0x62, 0x66, 0x66, 0x66, 0x66, 0x66, 0x26, 0x07, 0x66, 0xe9, 0x3e, 0x66, 0x66, 0x66, 0x36, - 0x1e, 0x66, 0x86, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x66, 0x70, 0x62, 0x66, 0x66, - 0x66, 0x66, 0x87, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x76, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0xf0, 0x86, 0x27, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x72, 0x60, 0x66, 0x7f, 0x21, 0x66, - 0x66, 0x26, 0x78, 0x63, 0x66, 0x78, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x60, 0x06, 0x27, - 0x66, 0x66, 0x66, 0x66, 0x76, 0x68, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x77, 0x66, 0x66, 0x66, - 0x66, 0x66, 0x66, 0x66, 0x66, 0x78, 0x62, 0x66, 0x66, 0x66, 0x66, 0x66, 0x26, 0x07, 0x66, 0x66, - 0xef, 0x17, 0x04, 0x84, 0x17, 0x63, 0x66, 0x86, 0x27, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, - 0x66, 0x70, 0x62, 0x66, 0x66, 0x66, 0x66, 0x87, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x16, 0x97, - 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x46, 0x27, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x75, - 0x60, 0x66, 0x66, 0x7b, 0x88, 0x88, 0xf4, 0x66, 0x66, 0x66, 0x74, 0x65, 0x66, 0x66, 0x66, 0x66, - 0x66, 0x66, 0x66, 0x06, 0x27, 0x66, 0x66, 0x66, 0x66, 0x76, 0x68, 0x66, 0x66, 0x66, 0x66, 0x66, - 0x66, 0x78, 0x65, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x70, 0x60, 0x66, 0x66, 0x66, 0x66, - 0x66, 0x06, 0x07, 0x66, 0x66, 0x7f, 0x6f, 0x66, 0x66, 0x66, 0x66, 0x66, 0x06, 0xa7, 0x66, 0x66, - 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x70, 0x62, 0x66, 0x66, 0x66, 0x66, 0x87, 0x66, 0x66, 0x66, - 0x66, 0x66, 0x66, 0xb6, 0xa7, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x56, 0x47, 0x66, 0x66, - 0x66, 0x66, 0x66, 0x66, 0x74, 0x60, 0x66, 0x73, 0x60, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x73, - 0x68, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x06, 0x27, 0x66, 0x66, 0x66, 0x66, 0x76, 0x68, - 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x73, 0x9e, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x79, - 0x97, 0x66, 0x66, 0x66, 0x66, 0x66, 0xe6, 0x07, 0x66, 0x06, 0x27, 0x66, 0x66, 0x66, 0x66, 0x66, - 0x66, 0x66, 0x71, 0x62, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x70, 0x62, 0x66, 0x66, 0x66, - 0x66, 0x87, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x74, 0x64, 0x66, 0x66, 0x66, 0x66, 0x66, - 0x66, 0x66, 0x74, 0x60, 0x66, 0x66, 0x66, 0x66, 0xb6, 0x77, 0x60, 0x66, 0x70, 0x65, 0x66, 0x66, - 0x66, 0x66, 0x66, 0x66, 0xf6, 0x87, 0x69, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x06, 0x27, 0x66, - 0x66, 0x66, 0x66, 0x76, 0x68, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x96, 0x7e, 0x6b, 0x66, 0x66, - 0x66, 0x66, 0x66, 0x66, 0x36, 0x7e, 0x6f, 0x66, 0x66, 0x66, 0x36, 0x8e, 0x07, 0x66, 0x36, 0xee, - 0x5a, 0x22, 0x22, 0x22, 0x69, 0x66, 0x66, 0x86, 0x47, 0x69, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, - 0x70, 0x62, 0x66, 0x66, 0x66, 0x66, 0x87, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x62, 0x36, 0x7e, - 0x58, 0x66, 0x66, 0x66, 0xa5, 0x6e, 0x66, 0x56, 0x77, 0x34, 0x66, 0x66, 0x03, 0x8e, 0xe9, 0x60, - 0x66, 0x36, 0x7e, 0x77, 0x77, 0x77, 0x77, 0xf8, 0x66, 0x66, 0x89, 0x17, 0x9f, 0x66, 0x66, 0x36, - 0x10, 0x62, 0x06, 0x27, 0x66, 0x66, 0x66, 0x66, 0x76, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, - 0x66, 0x36, 0x78, 0x77, 0x81, 0x78, 0x77, 0x87, 0x66, 0x66, 0x36, 0x71, 0xe7, 0x88, 0x71, 0x47, - 0x69, 0x08, 0x66, 0x09, 0x1e, 0x04, 0x00, 0x00, 0x40, 0x71, 0x47, 0x66, 0x66, 0xa9, 0x77, 0xe7, - 0x88, 0x7e, 0x77, 0x31, 0x66, 0x70, 0x62, 0x66, 0x66, 0x66, 0x66, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x60, 0x66, 0x66, 0x03, 0x88, 0x88, 0x48, 0x3b, 0x66, 0x66, 0x66, 0x66, 0x45, 0x88, - 0x88, 0x3a, 0x66, 0xf6, 0x62, 0x89, 0xfe, 0x66, 0x66, 0x66, 0x66, 0x66, 0xe2, 0xf7, 0x66, 0x66, - 0x36, 0x4b, 0x88, 0x88, 0x04, 0x63, 0x66, 0x26, 0x30, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, - 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, - 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x86, 0x27, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x75, - 0x64, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, - 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, - 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x36, 0x87, 0x66, 0x66, 0x66, 0x66, 0x66, - 0x66, 0x66, 0x17, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, - 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, - 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x7f, 0x6a, 0x66, 0x66, - 0x66, 0x66, 0x66, 0x66, 0x76, 0x61, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, - 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, - 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0xb6, 0x47, - 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x36, 0x87, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, - 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, - 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, - 0x66, 0x72, 0x61, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x74, 0x6f, 0x66, 0x66, 0x66, 0x66, 0x66, - 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, - 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, - 0x66, 0x66, 0x66, 0x66, 0x71, 0x6b, 0x66, 0x66, 0x66, 0x66, 0x66, 0x70, 0x68, 0x66, 0x66, 0x66, - 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, - 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, - 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x36, 0x7e, 0x54, 0x66, 0x66, 0x66, 0xb3, 0x71, 0x98, 0x66, - 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, - 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, - 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x36, 0x78, 0x77, 0x8e, 0xe8, 0x77, 0x17, - 0x6f, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, - 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, - 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0xb3, 0x8a, 0x88, - 0xa8, 0x3b, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, - 0x66, 0x66, 0x66, 0x66, + 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x85, 0x7e, + 0x77, 0x77, 0x63, 0x66, 0x66, 0x56, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, + 0x77, 0x77, 0xe7, 0xb8, 0x6c, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, + 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x36, + 0x78, 0x77, 0x77, 0x77, 0x37, 0x66, 0x66, 0x66, 0x75, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, + 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x17, 0x65, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, + 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, + 0x66, 0x26, 0x7e, 0x77, 0x77, 0x77, 0x77, 0x63, 0x66, 0x66, 0x56, 0x77, 0x77, 0x77, 0x77, 0x77, + 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x6b, 0x66, 0x66, 0x66, 0x66, 0x66, + 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, + 0x66, 0x66, 0x66, 0x96, 0x7e, 0x77, 0x77, 0x77, 0x77, 0x37, 0x66, 0x66, 0x66, 0x75, 0x77, 0x77, + 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x62, 0x66, 0x66, + 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, + 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x74, 0x77, 0x77, 0x77, 0x77, 0x77, 0x63, 0x66, 0x66, 0x56, + 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x17, + 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, + 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x79, 0x77, 0x77, 0x77, 0x77, 0x77, 0x37, 0x66, + 0x66, 0x66, 0x75, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, + 0x77, 0x77, 0xf7, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, + 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x06, 0x77, 0x77, 0x77, 0x77, 0x77, + 0x77, 0x63, 0x66, 0x66, 0x56, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, + 0x77, 0x77, 0x77, 0x77, 0x77, 0x64, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, + 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x74, 0x77, 0x77, + 0x77, 0x77, 0x77, 0x37, 0x66, 0x66, 0x66, 0x75, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, + 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x17, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, + 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x86, + 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x63, 0x66, 0x66, 0x56, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, + 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x61, 0x66, 0x66, 0x66, 0x66, 0x66, + 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, + 0x66, 0x66, 0x78, 0x77, 0x77, 0x77, 0x77, 0x77, 0x37, 0x66, 0x66, 0x66, 0x75, 0x77, 0x77, 0x77, + 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x17, 0x66, 0x66, 0x66, + 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, + 0x66, 0x66, 0x66, 0x66, 0x86, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x63, 0x66, 0x66, 0x56, 0x77, + 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x61, + 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, + 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x78, 0x77, 0x77, 0x77, 0x77, 0x77, 0x37, 0x66, 0x66, + 0x66, 0x75, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, + 0x77, 0x17, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, + 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0xa6, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, + 0x69, 0x66, 0x66, 0x56, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, + 0x77, 0x77, 0x77, 0x77, 0x61, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, + 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, + 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x75, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, + 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x17, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, + 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, + 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x56, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, + 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x61, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, + 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, + 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x75, 0x77, 0x77, 0x77, 0x77, + 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x17, 0x66, 0x66, 0x66, 0x66, + 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, + 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x56, 0x77, 0x77, + 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x61, 0x66, + 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, + 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, + 0x75, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, + 0x17, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, + 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, + 0x66, 0x66, 0x56, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, + 0x77, 0x77, 0x77, 0x61, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, + 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, + 0x66, 0x66, 0x66, 0x66, 0x66, 0x75, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, + 0x77, 0x77, 0x77, 0x77, 0x77, 0x17, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, + 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0xd6, 0x88, 0x88, + 0x88, 0x88, 0x88, 0x88, 0x69, 0x66, 0x66, 0x56, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, + 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x61, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, + 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, + 0x78, 0x77, 0x77, 0x77, 0x77, 0x77, 0x37, 0x66, 0x66, 0x66, 0x75, 0x77, 0x77, 0x77, 0x77, 0x77, + 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x17, 0x66, 0x66, 0x66, 0x66, 0x66, + 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, + 0x66, 0x66, 0x86, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x63, 0x66, 0x66, 0x56, 0x77, 0x77, 0x77, + 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x61, 0x66, 0x66, + 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, + 0x66, 0x66, 0x66, 0x66, 0x66, 0x78, 0x77, 0x77, 0x77, 0x77, 0x77, 0x37, 0x66, 0x66, 0x66, 0x75, + 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x17, + 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, + 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x86, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x63, 0x66, + 0x66, 0x56, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, + 0x77, 0x77, 0x61, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, + 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x78, 0x77, 0x77, 0x77, 0x77, 0x77, + 0x37, 0x66, 0x66, 0x66, 0x75, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, + 0x77, 0x77, 0x77, 0x77, 0x17, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, + 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x86, 0x77, 0x77, 0x77, + 0x77, 0x77, 0x77, 0x63, 0x66, 0x66, 0x56, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, + 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x61, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, + 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x78, + 0x77, 0x77, 0x77, 0x77, 0x77, 0x37, 0x66, 0x66, 0x66, 0x75, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, + 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x17, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, + 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, + 0x66, 0x86, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x63, 0x66, 0x66, 0x56, 0x77, 0x77, 0x77, 0x77, + 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x61, 0x66, 0x66, 0x66, + 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, + 0x66, 0x66, 0x66, 0x66, 0x78, 0x77, 0x77, 0x77, 0x77, 0x77, 0x37, 0x66, 0x66, 0x66, 0x75, 0x77, + 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x17, 0x66, + 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, + 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x86, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x63, 0x66, 0x66, + 0x56, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, + 0x77, 0x61, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, + 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x78, 0x77, 0x77, 0x77, 0x77, 0x77, 0x37, + 0x66, 0x66, 0x66, 0x75, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, + 0x77, 0x77, 0x77, 0x17, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, + 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x86, 0x77, 0x77, 0x77, 0x77, + 0x77, 0x77, 0x63, 0x66, 0x66, 0x56, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, + 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x61, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, + 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x99, 0x99, + 0x99, 0x99, 0x99, 0x99, 0xc9, 0x66, 0x66, 0x66, 0x9c, 0x99, 0x99, 0x99, 0x99, 0x99, 0x99, 0x99, + 0x99, 0x99, 0x99, 0x99, 0x99, 0x99, 0x99, 0x99, 0x99, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, + 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, + 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, + 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, + 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, + 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, + 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, + 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, + 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, + 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, + 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, + 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, + 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, + 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, + 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, + 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, + 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, + 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, + 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, + 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, + 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x56, + 0xbb, 0xbb, 0xbb, 0xbb, 0xbb, 0xbb, 0x69, 0x66, 0x66, 0x96, 0xbb, 0xbb, 0xbb, 0xbb, 0xbb, 0xbb, + 0x63, 0x66, 0x66, 0x66, 0xbf, 0xbb, 0xbb, 0xbb, 0xbb, 0xbb, 0x6f, 0x66, 0x66, 0x66, 0x66, 0x66, + 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, + 0x66, 0x66, 0x78, 0x77, 0x77, 0x77, 0x77, 0x77, 0x37, 0x66, 0x66, 0x66, 0x75, 0x77, 0x77, 0x77, + 0x77, 0x77, 0xa7, 0x66, 0x66, 0x66, 0xe6, 0x77, 0x77, 0x77, 0x77, 0x77, 0x17, 0x66, 0x66, 0x66, + 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, + 0x66, 0x66, 0x66, 0x66, 0x86, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x63, 0x66, 0x66, 0x56, 0x77, + 0x77, 0x77, 0x77, 0x77, 0x77, 0x6a, 0x66, 0x66, 0x66, 0x7e, 0x77, 0x77, 0x77, 0x77, 0x77, 0x61, + 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, + 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x78, 0x77, 0x77, 0x77, 0x77, 0x77, 0x37, 0x66, 0x66, + 0x66, 0x75, 0x77, 0x77, 0x77, 0x77, 0x77, 0xa7, 0x66, 0x66, 0x66, 0xe6, 0x77, 0x77, 0x77, 0x77, + 0x77, 0x17, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, + 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x86, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, + 0x63, 0x66, 0x66, 0x56, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x6a, 0x66, 0x66, 0x66, 0x7e, 0x77, + 0x77, 0x77, 0x77, 0x77, 0x61, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, + 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x74, 0x77, 0x77, 0x77, + 0x77, 0x77, 0x37, 0x66, 0x66, 0x66, 0x75, 0x77, 0x77, 0x77, 0x77, 0x77, 0xa7, 0x66, 0x66, 0x66, + 0xe6, 0x77, 0x77, 0x77, 0x77, 0x77, 0x17, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, + 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0xa6, 0x77, + 0x77, 0x77, 0x77, 0x77, 0x77, 0x63, 0x66, 0x66, 0x56, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x6a, + 0x66, 0x66, 0x66, 0x7e, 0x77, 0x77, 0x77, 0x77, 0x77, 0x68, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, + 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, + 0x66, 0x72, 0x77, 0x77, 0x77, 0x77, 0x77, 0x37, 0x66, 0x66, 0x66, 0x75, 0x77, 0x77, 0x77, 0x77, + 0x77, 0xa7, 0x66, 0x66, 0x66, 0xe6, 0x77, 0x77, 0x77, 0x77, 0x77, 0x07, 0x66, 0x66, 0x66, 0x66, + 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, + 0x66, 0x66, 0x66, 0x66, 0x71, 0x77, 0x77, 0x77, 0x77, 0x77, 0x63, 0x66, 0x66, 0x56, 0x77, 0x77, + 0x77, 0x77, 0x77, 0x77, 0x6a, 0x66, 0x66, 0x66, 0x7e, 0x77, 0x77, 0x77, 0x77, 0x77, 0x69, 0x66, + 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, + 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x56, 0x77, 0x77, 0x77, 0x77, 0x77, 0x37, 0x66, 0x66, 0x66, + 0x75, 0x77, 0x77, 0x77, 0x77, 0x77, 0xa7, 0x66, 0x66, 0x66, 0xe6, 0x77, 0x77, 0x77, 0x77, 0x77, + 0x6a, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, + 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0xa6, 0x77, 0x77, 0x77, 0x77, 0x77, 0x63, + 0x66, 0x66, 0x56, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x6a, 0x66, 0x66, 0x66, 0x7e, 0x77, 0x77, + 0x77, 0x77, 0xc8, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, + 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x06, 0x77, 0x77, 0x77, + 0x77, 0x37, 0x66, 0x66, 0x66, 0x75, 0x77, 0x77, 0x77, 0x77, 0x77, 0xa7, 0x66, 0x66, 0x66, 0xe6, + 0x77, 0x77, 0x77, 0x77, 0xc4, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, + 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x36, + 0x78, 0x77, 0x77, 0x77, 0x63, 0x66, 0x66, 0x56, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x6a, 0x66, + 0x66, 0x66, 0x7e, 0x77, 0x77, 0x17, 0x65, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, + 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, + 0x66, 0x66, 0x66, 0xf9, 0x00, 0x00, 0x90, 0x66, 0x66, 0x66, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x20, 0x66, 0x66, 0x66, 0xb6, 0x00, 0x00, 0x3f, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, + 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, + 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, + 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, + 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, + 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, + 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, + 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, + 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, + 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, + 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, + 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, + 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, + 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, + 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, + 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, + 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, + 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, + 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, + 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, + 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, + 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, + 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, + 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, + 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, + 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, + 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, + 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, + 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, + 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, + 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, + 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, + 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, + 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, + 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, + 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, + 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, + 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x36, 0xf8, 0x66, 0x66, 0x66, 0x66, + 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, + 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, + 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x72, 0x60, 0x66, + 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, + 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x76, 0x68, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, + 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x26, + 0x07, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, + 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x87, 0x66, 0x66, 0x66, 0x66, 0x66, + 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, + 0x66, 0x66, 0x72, 0x60, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, + 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x76, 0x68, 0x66, 0x66, + 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, + 0x66, 0x66, 0x66, 0x66, 0x26, 0x07, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, + 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x87, + 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, + 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x72, 0x60, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, + 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, + 0x66, 0x76, 0x68, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, + 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x26, 0x07, 0x66, 0x66, 0x66, 0x66, 0x66, + 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, + 0x66, 0x66, 0x66, 0x66, 0x87, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, + 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x72, 0x60, 0x66, 0x66, + 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, + 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x76, 0x68, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, + 0x66, 0x26, 0x22, 0x62, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x29, 0x22, 0x62, 0x66, 0x26, 0x07, + 0x66, 0x66, 0x66, 0x36, 0x22, 0x22, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x23, 0x22, 0x69, + 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x29, 0x22, 0x62, 0x87, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, + 0x66, 0x66, 0x36, 0x74, 0x77, 0x77, 0x0e, 0x69, 0x66, 0x66, 0x66, 0x26, 0x74, 0x77, 0x77, 0x47, + 0x63, 0x72, 0x60, 0x66, 0x66, 0x1f, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x62, 0x66, 0x49, 0x7e, + 0x77, 0x77, 0x34, 0x66, 0x66, 0x06, 0x67, 0x96, 0x74, 0x77, 0x77, 0x72, 0x68, 0x66, 0x66, 0x66, + 0x66, 0x66, 0x66, 0x66, 0xb6, 0x77, 0x04, 0x52, 0x10, 0x17, 0x63, 0x66, 0x66, 0xa6, 0x77, 0x08, + 0xff, 0x40, 0xe7, 0x2f, 0x07, 0x66, 0x66, 0x74, 0xf1, 0x22, 0xf2, 0x71, 0xa7, 0x00, 0x90, 0x66, + 0xe2, 0x87, 0x50, 0x02, 0x78, 0xfe, 0x66, 0x66, 0x70, 0x39, 0x7e, 0x04, 0x00, 0x64, 0x87, 0x66, + 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0xb6, 0x87, 0x63, 0x66, 0x66, 0x46, 0x17, 0x69, 0x66, 0xa6, + 0xe7, 0x62, 0x66, 0x66, 0x36, 0x78, 0x7b, 0x60, 0x66, 0x7a, 0x64, 0x66, 0x66, 0x66, 0x74, 0x6a, + 0x66, 0x66, 0x73, 0x5e, 0x66, 0x66, 0x66, 0x7f, 0x37, 0x66, 0x06, 0x27, 0xe8, 0x63, 0x66, 0x66, + 0x76, 0x68, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x26, 0xe7, 0x69, 0x66, 0x66, 0x66, 0x46, 0xa7, + 0x66, 0x26, 0xe7, 0x63, 0x66, 0x66, 0x66, 0x66, 0x78, 0x07, 0x66, 0x73, 0x61, 0x66, 0x66, 0x66, + 0x66, 0x71, 0x63, 0x66, 0xe9, 0x27, 0x66, 0x66, 0x66, 0x66, 0x7b, 0x68, 0x66, 0x70, 0xe8, 0x63, + 0x66, 0x66, 0x66, 0x87, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x78, 0x62, 0x66, 0x66, 0x66, + 0x66, 0x79, 0x97, 0x66, 0x74, 0x6b, 0x66, 0x66, 0x66, 0x66, 0x26, 0x77, 0x60, 0x06, 0xb7, 0x66, + 0x66, 0x66, 0x66, 0xb6, 0xb7, 0x66, 0x06, 0x07, 0x66, 0x66, 0x66, 0x66, 0x66, 0x78, 0x65, 0x06, + 0x77, 0x6b, 0x66, 0x66, 0x66, 0x76, 0x68, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x73, 0x68, 0x66, + 0x66, 0x66, 0x66, 0x66, 0x74, 0x6f, 0x79, 0x9e, 0x66, 0x66, 0x66, 0x66, 0x66, 0x86, 0x07, 0x66, + 0x78, 0x62, 0x66, 0x66, 0x66, 0x66, 0x72, 0x64, 0x66, 0x7e, 0x69, 0x66, 0x66, 0x66, 0x66, 0xf6, + 0x47, 0x66, 0x70, 0x6e, 0x66, 0x66, 0x66, 0x66, 0x87, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x06, + 0x07, 0x66, 0x66, 0x66, 0x66, 0x66, 0xb6, 0xa7, 0x56, 0x47, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, + 0x7a, 0x60, 0x86, 0x27, 0x66, 0x66, 0x66, 0x66, 0x26, 0x87, 0x66, 0x72, 0x68, 0x66, 0x66, 0x66, + 0x66, 0x66, 0x73, 0x68, 0x06, 0x47, 0x66, 0x66, 0x66, 0x66, 0x76, 0x68, 0x66, 0x66, 0x66, 0x66, + 0x66, 0x66, 0x78, 0x62, 0x66, 0x66, 0x66, 0x66, 0x66, 0x72, 0x68, 0x70, 0x60, 0x66, 0x66, 0x66, + 0x66, 0x66, 0xb6, 0x07, 0x66, 0x74, 0x62, 0x66, 0x66, 0x66, 0x66, 0x72, 0x6a, 0x06, 0x07, 0x66, + 0x66, 0x66, 0x66, 0x66, 0x66, 0x77, 0x66, 0x70, 0x60, 0x66, 0x66, 0x66, 0x66, 0x87, 0x66, 0x66, + 0x66, 0x66, 0x66, 0x66, 0xe6, 0x37, 0x66, 0x66, 0x66, 0x66, 0x66, 0x26, 0x87, 0x46, 0x27, 0x66, + 0x66, 0x66, 0x66, 0x66, 0x66, 0x72, 0x60, 0xb6, 0xa7, 0x66, 0x66, 0x66, 0x66, 0xa6, 0xf7, 0x66, + 0x74, 0x6f, 0x66, 0x66, 0x66, 0x66, 0x66, 0x76, 0x67, 0x06, 0x27, 0x66, 0x66, 0x66, 0x66, 0x76, + 0x68, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x68, + 0x78, 0x62, 0x66, 0x66, 0x66, 0x66, 0x66, 0x26, 0x07, 0x66, 0xe9, 0x3e, 0x66, 0x66, 0x66, 0x36, + 0x1e, 0x66, 0x86, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x66, 0x70, 0x62, 0x66, 0x66, + 0x66, 0x66, 0x87, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x76, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0xf0, 0x86, 0x27, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x72, 0x60, 0x66, 0x7f, 0x21, 0x66, + 0x66, 0x26, 0x78, 0x63, 0x66, 0x78, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x60, 0x06, 0x27, + 0x66, 0x66, 0x66, 0x66, 0x76, 0x68, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x77, 0x66, 0x66, 0x66, + 0x66, 0x66, 0x66, 0x66, 0x66, 0x78, 0x62, 0x66, 0x66, 0x66, 0x66, 0x66, 0x26, 0x07, 0x66, 0x66, + 0xef, 0x17, 0x04, 0x84, 0x17, 0x63, 0x66, 0x86, 0x27, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, + 0x66, 0x70, 0x62, 0x66, 0x66, 0x66, 0x66, 0x87, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x16, 0x97, + 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x46, 0x27, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x75, + 0x60, 0x66, 0x66, 0x7b, 0x88, 0x88, 0xf4, 0x66, 0x66, 0x66, 0x74, 0x65, 0x66, 0x66, 0x66, 0x66, + 0x66, 0x66, 0x66, 0x06, 0x27, 0x66, 0x66, 0x66, 0x66, 0x76, 0x68, 0x66, 0x66, 0x66, 0x66, 0x66, + 0x66, 0x78, 0x65, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x70, 0x60, 0x66, 0x66, 0x66, 0x66, + 0x66, 0x06, 0x07, 0x66, 0x66, 0x7f, 0x6f, 0x66, 0x66, 0x66, 0x66, 0x66, 0x06, 0xa7, 0x66, 0x66, + 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x70, 0x62, 0x66, 0x66, 0x66, 0x66, 0x87, 0x66, 0x66, 0x66, + 0x66, 0x66, 0x66, 0xb6, 0xa7, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x56, 0x47, 0x66, 0x66, + 0x66, 0x66, 0x66, 0x66, 0x74, 0x60, 0x66, 0x73, 0x60, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x73, + 0x68, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x06, 0x27, 0x66, 0x66, 0x66, 0x66, 0x76, 0x68, + 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x73, 0x9e, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x79, + 0x97, 0x66, 0x66, 0x66, 0x66, 0x66, 0xe6, 0x07, 0x66, 0x06, 0x27, 0x66, 0x66, 0x66, 0x66, 0x66, + 0x66, 0x66, 0x71, 0x62, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x70, 0x62, 0x66, 0x66, 0x66, + 0x66, 0x87, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x74, 0x64, 0x66, 0x66, 0x66, 0x66, 0x66, + 0x66, 0x66, 0x74, 0x60, 0x66, 0x66, 0x66, 0x66, 0xb6, 0x77, 0x60, 0x66, 0x70, 0x65, 0x66, 0x66, + 0x66, 0x66, 0x66, 0x66, 0xf6, 0x87, 0x69, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x06, 0x27, 0x66, + 0x66, 0x66, 0x66, 0x76, 0x68, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x96, 0x7e, 0x6b, 0x66, 0x66, + 0x66, 0x66, 0x66, 0x66, 0x36, 0x7e, 0x6f, 0x66, 0x66, 0x66, 0x36, 0x8e, 0x07, 0x66, 0x36, 0xee, + 0x5a, 0x22, 0x22, 0x22, 0x69, 0x66, 0x66, 0x86, 0x47, 0x69, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, + 0x70, 0x62, 0x66, 0x66, 0x66, 0x66, 0x87, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x62, 0x36, 0x7e, + 0x58, 0x66, 0x66, 0x66, 0xa5, 0x6e, 0x66, 0x56, 0x77, 0x34, 0x66, 0x66, 0x03, 0x8e, 0xe9, 0x60, + 0x66, 0x36, 0x7e, 0x77, 0x77, 0x77, 0x77, 0xf8, 0x66, 0x66, 0x89, 0x17, 0x9f, 0x66, 0x66, 0x36, + 0x10, 0x62, 0x06, 0x27, 0x66, 0x66, 0x66, 0x66, 0x76, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, + 0x66, 0x36, 0x78, 0x77, 0x81, 0x78, 0x77, 0x87, 0x66, 0x66, 0x36, 0x71, 0xe7, 0x88, 0x71, 0x47, + 0x69, 0x08, 0x66, 0x09, 0x1e, 0x04, 0x00, 0x00, 0x40, 0x71, 0x47, 0x66, 0x66, 0xa9, 0x77, 0xe7, + 0x88, 0x7e, 0x77, 0x31, 0x66, 0x70, 0x62, 0x66, 0x66, 0x66, 0x66, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x60, 0x66, 0x66, 0x03, 0x88, 0x88, 0x48, 0x3b, 0x66, 0x66, 0x66, 0x66, 0x45, 0x88, + 0x88, 0x3a, 0x66, 0xf6, 0x62, 0x89, 0xfe, 0x66, 0x66, 0x66, 0x66, 0x66, 0xe2, 0xf7, 0x66, 0x66, + 0x36, 0x4b, 0x88, 0x88, 0x04, 0x63, 0x66, 0x26, 0x30, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, + 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, + 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x86, 0x27, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x75, + 0x64, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, + 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, + 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x36, 0x87, 0x66, 0x66, 0x66, 0x66, 0x66, + 0x66, 0x66, 0x17, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, + 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, + 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x7f, 0x6a, 0x66, 0x66, + 0x66, 0x66, 0x66, 0x66, 0x76, 0x61, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, + 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, + 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0xb6, 0x47, + 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x36, 0x87, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, + 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, + 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, + 0x66, 0x72, 0x61, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x74, 0x6f, 0x66, 0x66, 0x66, 0x66, 0x66, + 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, + 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, + 0x66, 0x66, 0x66, 0x66, 0x71, 0x6b, 0x66, 0x66, 0x66, 0x66, 0x66, 0x70, 0x68, 0x66, 0x66, 0x66, + 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, + 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, + 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x36, 0x7e, 0x54, 0x66, 0x66, 0x66, 0xb3, 0x71, 0x98, 0x66, + 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, + 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, + 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x36, 0x78, 0x77, 0x8e, 0xe8, 0x77, 0x17, + 0x6f, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, + 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, + 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0xb3, 0x8a, 0x88, + 0xa8, 0x3b, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, + 0x66, 0x66, 0x66, 0x66, }; - unsigned int const C_icon_bootloader_colors[] = { - 0x00dadada, - 0x00e7e7e7, - 0x00cccccc, - 0x00f8f8f8, + 0x00dadada, + 0x00e7e7e7, + 0x00cccccc, + 0x00f8f8f8, }; unsigned char const C_icon_bootloader_bitmap[] = { - 0xff, 0xff, 0xff, 0xff, 0x7f, 0xa0, 0xaa, 0xd0, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0x1f, 0xaa, 0xaa, 0xaa, 0x4a, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x8f, 0xaa, 0xaa, 0xaa, - 0xaa, 0x2a, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x8f, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0x2a, 0xff, - 0xff, 0xff, 0xff, 0xff, 0x9f, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0x6a, 0xff, 0xff, 0xff, 0xff, - 0x3f, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xca, 0xff, 0xff, 0xff, 0xff, 0xa8, 0xaa, 0xaa, - 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xf2, 0xff, 0xff, 0xff, 0xa3, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, - 0xaa, 0xaa, 0xfc, 0xff, 0xff, 0x8f, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0x2a, 0xff, - 0xff, 0x3f, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xca, 0xff, 0xff, 0xa9, 0xaa, - 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xf6, 0xff, 0xaf, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, - 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xff, 0x3f, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0x96, 0x12, 0xaa, - 0xaa, 0xca, 0xff, 0xab, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xda, 0xc7, 0xaf, 0xaa, 0xaa, 0xfe, 0x8f, - 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xfc, 0x7f, 0xaa, 0xaa, 0x2a, 0xff, 0xaa, 0xaa, 0xaa, 0x2a, - 0x85, 0xaa, 0xca, 0xd7, 0xa7, 0xaa, 0xaa, 0xfa, 0xa7, 0xaa, 0xaa, 0xaa, 0xfc, 0xa9, 0xca, 0x9f, - 0xf2, 0xa7, 0xaa, 0xaa, 0x3d, 0xaa, 0xaa, 0x4a, 0xca, 0x9f, 0x96, 0xfd, 0xa8, 0xff, 0xaa, 0xaa, - 0xca, 0xab, 0xaa, 0x2a, 0x7f, 0xff, 0xd7, 0x47, 0x9f, 0xf2, 0xa7, 0xaa, 0xaa, 0x9e, 0xaa, 0xaa, - 0xfc, 0xff, 0xff, 0xff, 0xe8, 0xdf, 0xa3, 0xaa, 0xaa, 0x6a, 0xa8, 0xaa, 0x6a, 0xff, 0xff, 0xff, - 0xaf, 0xfc, 0x7f, 0xaa, 0xaa, 0xaa, 0x82, 0xaa, 0xaa, 0xfa, 0x3f, 0xd0, 0x3f, 0xda, 0xc7, 0xaf, - 0xaa, 0xaa, 0x2a, 0xaa, 0xaa, 0x2a, 0x7f, 0xaa, 0xf6, 0xa7, 0x92, 0x92, 0xaa, 0xaa, 0xaa, 0xaa, - 0xaa, 0xea, 0xff, 0xab, 0xaa, 0xff, 0x8f, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xfe, 0xbf, - 0xaa, 0xda, 0xff, 0xa8, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xea, 0xff, 0xab, 0xaa, 0xfd, 0x8f, - 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xf6, 0xbf, 0xaa, 0xfa, 0xff, 0xa8, 0xaa, 0xaa, 0xaa, - 0xaa, 0xaa, 0xaa, 0xaa, 0xf2, 0xa7, 0x6a, 0x7f, 0x6a, 0x29, 0xa9, 0xaa, 0xaa, 0xaa, 0xa8, 0xaa, - 0xaa, 0xff, 0x03, 0xfd, 0xa3, 0x7d, 0xfc, 0xaa, 0xaa, 0xaa, 0x82, 0xaa, 0xaa, 0xf6, 0xff, 0xff, - 0xff, 0xc8, 0xff, 0xa7, 0xaa, 0xaa, 0x2a, 0xa9, 0xaa, 0xea, 0xff, 0xff, 0xff, 0x9f, 0xfe, 0x3d, - 0xaa, 0xaa, 0xaa, 0xb6, 0xaa, 0xaa, 0xf2, 0xf7, 0x7f, 0x7d, 0xf4, 0x29, 0x7f, 0xaa, 0xaa, 0xea, - 0xa3, 0xaa, 0xaa, 0xa4, 0xfc, 0x69, 0xd9, 0x8f, 0xfa, 0xaf, 0xaa, 0xaa, 0x7c, 0xaa, 0xaa, 0xaa, - 0xca, 0x9f, 0xaa, 0xfc, 0x29, 0x7f, 0xaa, 0xaa, 0xda, 0xaf, 0xaa, 0xaa, 0xaa, 0x52, 0xa8, 0xaa, - 0x7e, 0x7d, 0xaa, 0xaa, 0xaa, 0xff, 0xa8, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xca, 0xff, 0xa7, 0xaa, - 0xaa, 0xf2, 0xbf, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0x7d, 0xfc, 0xaa, 0xaa, 0xea, 0xff, 0xa3, - 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0x6a, 0x29, 0xa1, 0xaa, 0xaa, 0xfc, 0xff, 0xaa, 0xaa, 0xaa, 0xaa, - 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xfa, 0xff, 0x9f, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, - 0xaa, 0xaa, 0x6a, 0xff, 0xff, 0xa3, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xfc, - 0xff, 0xff, 0xa8, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xf2, 0xff, 0xff, 0x3f, 0xaa, - 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xca, 0xff, 0xff, 0xff, 0x8f, 0xaa, 0xaa, 0xaa, 0xaa, - 0xaa, 0xaa, 0xaa, 0x2a, 0xff, 0xff, 0xff, 0xff, 0xa3, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, - 0xfc, 0xff, 0xff, 0xff, 0xff, 0xa9, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xf6, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xa8, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xf2, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xa8, - 0xaa, 0xaa, 0xaa, 0xaa, 0xf2, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xa1, 0xaa, 0xaa, 0xaa, - 0xf4, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x07, 0xaa, 0x0a, 0xfd, 0xff, 0xff, 0xff, - 0xff, + 0xff, 0xff, 0xff, 0xff, 0x7f, 0xa0, 0xaa, 0xd0, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0x1f, 0xaa, 0xaa, 0xaa, 0x4a, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x8f, 0xaa, 0xaa, 0xaa, + 0xaa, 0x2a, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x8f, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0x2a, 0xff, + 0xff, 0xff, 0xff, 0xff, 0x9f, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0x6a, 0xff, 0xff, 0xff, 0xff, + 0x3f, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xca, 0xff, 0xff, 0xff, 0xff, 0xa8, 0xaa, 0xaa, + 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xf2, 0xff, 0xff, 0xff, 0xa3, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, + 0xaa, 0xaa, 0xfc, 0xff, 0xff, 0x8f, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0x2a, 0xff, + 0xff, 0x3f, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xca, 0xff, 0xff, 0xa9, 0xaa, + 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xf6, 0xff, 0xaf, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, + 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xff, 0x3f, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0x96, 0x12, 0xaa, + 0xaa, 0xca, 0xff, 0xab, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xda, 0xc7, 0xaf, 0xaa, 0xaa, 0xfe, 0x8f, + 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xfc, 0x7f, 0xaa, 0xaa, 0x2a, 0xff, 0xaa, 0xaa, 0xaa, 0x2a, + 0x85, 0xaa, 0xca, 0xd7, 0xa7, 0xaa, 0xaa, 0xfa, 0xa7, 0xaa, 0xaa, 0xaa, 0xfc, 0xa9, 0xca, 0x9f, + 0xf2, 0xa7, 0xaa, 0xaa, 0x3d, 0xaa, 0xaa, 0x4a, 0xca, 0x9f, 0x96, 0xfd, 0xa8, 0xff, 0xaa, 0xaa, + 0xca, 0xab, 0xaa, 0x2a, 0x7f, 0xff, 0xd7, 0x47, 0x9f, 0xf2, 0xa7, 0xaa, 0xaa, 0x9e, 0xaa, 0xaa, + 0xfc, 0xff, 0xff, 0xff, 0xe8, 0xdf, 0xa3, 0xaa, 0xaa, 0x6a, 0xa8, 0xaa, 0x6a, 0xff, 0xff, 0xff, + 0xaf, 0xfc, 0x7f, 0xaa, 0xaa, 0xaa, 0x82, 0xaa, 0xaa, 0xfa, 0x3f, 0xd0, 0x3f, 0xda, 0xc7, 0xaf, + 0xaa, 0xaa, 0x2a, 0xaa, 0xaa, 0x2a, 0x7f, 0xaa, 0xf6, 0xa7, 0x92, 0x92, 0xaa, 0xaa, 0xaa, 0xaa, + 0xaa, 0xea, 0xff, 0xab, 0xaa, 0xff, 0x8f, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xfe, 0xbf, + 0xaa, 0xda, 0xff, 0xa8, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xea, 0xff, 0xab, 0xaa, 0xfd, 0x8f, + 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xf6, 0xbf, 0xaa, 0xfa, 0xff, 0xa8, 0xaa, 0xaa, 0xaa, + 0xaa, 0xaa, 0xaa, 0xaa, 0xf2, 0xa7, 0x6a, 0x7f, 0x6a, 0x29, 0xa9, 0xaa, 0xaa, 0xaa, 0xa8, 0xaa, + 0xaa, 0xff, 0x03, 0xfd, 0xa3, 0x7d, 0xfc, 0xaa, 0xaa, 0xaa, 0x82, 0xaa, 0xaa, 0xf6, 0xff, 0xff, + 0xff, 0xc8, 0xff, 0xa7, 0xaa, 0xaa, 0x2a, 0xa9, 0xaa, 0xea, 0xff, 0xff, 0xff, 0x9f, 0xfe, 0x3d, + 0xaa, 0xaa, 0xaa, 0xb6, 0xaa, 0xaa, 0xf2, 0xf7, 0x7f, 0x7d, 0xf4, 0x29, 0x7f, 0xaa, 0xaa, 0xea, + 0xa3, 0xaa, 0xaa, 0xa4, 0xfc, 0x69, 0xd9, 0x8f, 0xfa, 0xaf, 0xaa, 0xaa, 0x7c, 0xaa, 0xaa, 0xaa, + 0xca, 0x9f, 0xaa, 0xfc, 0x29, 0x7f, 0xaa, 0xaa, 0xda, 0xaf, 0xaa, 0xaa, 0xaa, 0x52, 0xa8, 0xaa, + 0x7e, 0x7d, 0xaa, 0xaa, 0xaa, 0xff, 0xa8, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xca, 0xff, 0xa7, 0xaa, + 0xaa, 0xf2, 0xbf, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0x7d, 0xfc, 0xaa, 0xaa, 0xea, 0xff, 0xa3, + 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0x6a, 0x29, 0xa1, 0xaa, 0xaa, 0xfc, 0xff, 0xaa, 0xaa, 0xaa, 0xaa, + 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xfa, 0xff, 0x9f, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, + 0xaa, 0xaa, 0x6a, 0xff, 0xff, 0xa3, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xfc, + 0xff, 0xff, 0xa8, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xf2, 0xff, 0xff, 0x3f, 0xaa, + 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xca, 0xff, 0xff, 0xff, 0x8f, 0xaa, 0xaa, 0xaa, 0xaa, + 0xaa, 0xaa, 0xaa, 0x2a, 0xff, 0xff, 0xff, 0xff, 0xa3, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, + 0xfc, 0xff, 0xff, 0xff, 0xff, 0xa9, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xf6, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xa8, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xf2, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xa8, + 0xaa, 0xaa, 0xaa, 0xaa, 0xf2, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xa1, 0xaa, 0xaa, 0xaa, + 0xf4, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x07, 0xaa, 0x0a, 0xfd, 0xff, 0xff, 0xff, + 0xff, }; - unsigned int const C_logo_ledger_blue_colors[] = { - 0x00989aa0, - 0x00cacbcf, - 0x00eaeaeb, - 0x00656872, - 0x004c505c, - 0x00f9f9f9, - 0x00333746, - 0x00585c67, - 0x003f4351, - 0x00ededee, - 0x0082848d, - 0x00b3b5ba, - 0x00f6f6f6, - 0x0071747d, - 0x0062656f, - 0x00e0e1e2, + 0x00989aa0, + 0x00cacbcf, + 0x00eaeaeb, + 0x00656872, + 0x004c505c, + 0x00f9f9f9, + 0x00333746, + 0x00585c67, + 0x003f4351, + 0x00ededee, + 0x0082848d, + 0x00b3b5ba, + 0x00f6f6f6, + 0x0071747d, + 0x0062656f, + 0x00e0e1e2, }; unsigned char const C_logo_ledger_blue_bitmap[] = { - 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, - 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x09, 0x87, 0x66, 0x5e, 0x55, 0x55, 0x68, 0x66, 0x66, 0x66, - 0x66, 0x66, 0x66, 0x66, 0x86, 0xbe, 0x5c, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, - 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, - 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, - 0x55, 0xf5, 0x64, 0x66, 0x66, 0x5e, 0x55, 0x55, 0x68, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, - 0x66, 0x66, 0x27, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, - 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, - 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x49, 0x66, 0x66, - 0x66, 0x5e, 0x55, 0x55, 0x68, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0xe6, 0x5c, - 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, - 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, - 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x60, 0x66, 0x66, 0x66, 0x5e, 0x55, 0x55, - 0x68, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x5b, 0x55, 0x55, 0x55, 0x55, - 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, - 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, - 0x55, 0x55, 0x55, 0x55, 0x55, 0x67, 0x66, 0x66, 0x66, 0x5e, 0x55, 0x55, 0x68, 0x66, 0x66, 0x66, - 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x5d, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, - 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, - 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, - 0x55, 0x66, 0x66, 0x66, 0x66, 0x5e, 0x55, 0x55, 0x68, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, - 0x66, 0x66, 0x66, 0x54, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, - 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, - 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x66, 0x66, 0x66, - 0x66, 0x5e, 0x55, 0x55, 0x68, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x54, - 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, - 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, - 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x66, 0x66, 0x66, 0x66, 0x5e, 0x55, 0x55, - 0x68, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x54, 0x55, 0x55, 0x55, 0x55, - 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, - 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, - 0x55, 0x55, 0x55, 0x55, 0x55, 0x77, 0x77, 0x77, 0x77, 0x5a, 0x55, 0x55, 0x68, 0x66, 0x66, 0x66, - 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x54, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, - 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, - 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, - 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x68, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, - 0x66, 0x66, 0x66, 0x54, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, - 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, - 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, - 0x55, 0x55, 0x55, 0x55, 0x68, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x54, - 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, - 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, - 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, - 0x68, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x54, 0x55, 0x55, 0x55, 0x55, - 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, - 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, - 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x68, 0x66, 0x66, 0x66, - 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x54, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, - 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, - 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, - 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x68, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, - 0x66, 0x66, 0x66, 0x54, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, - 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, - 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x88, 0x88, 0x88, - 0x88, 0x5d, 0x55, 0x55, 0x68, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x54, - 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, - 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, - 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x66, 0x66, 0x66, 0x66, 0x5e, 0x55, 0x55, - 0x68, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x54, 0x55, 0x55, 0x55, 0x55, - 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, - 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, - 0x55, 0x55, 0x55, 0x55, 0x55, 0x66, 0x66, 0x66, 0x66, 0x5e, 0x55, 0x55, 0x68, 0x66, 0x66, 0x66, - 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x54, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, - 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, - 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, - 0x55, 0x66, 0x66, 0x66, 0x66, 0x5e, 0x55, 0x55, 0x68, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, - 0x66, 0x66, 0x66, 0x54, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, - 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, - 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x66, 0x66, 0x66, - 0x66, 0x5e, 0x55, 0x55, 0x68, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x54, - 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, - 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, - 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x66, 0x66, 0x66, 0x66, 0x5e, 0x55, 0x55, - 0x68, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x54, 0x55, 0x55, 0x55, 0x55, - 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, - 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, - 0x55, 0x55, 0x55, 0x55, 0x55, 0x66, 0x66, 0x66, 0x66, 0x5e, 0x55, 0x55, 0x68, 0x66, 0x66, 0x66, - 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x54, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, - 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, - 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, - 0x55, 0x66, 0x66, 0x66, 0x66, 0x5e, 0x55, 0x55, 0x68, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, - 0x66, 0x66, 0x66, 0x54, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, - 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, - 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x44, 0x44, 0x44, - 0x44, 0x5d, 0x55, 0x55, 0x47, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x5e, - 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, - 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, - 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, - 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, - 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, - 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, - 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, - 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, - 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, - 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, - 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, - 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, - 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, - 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, - 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, - 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, - 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, - 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, - 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, - 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, - 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, - 0x55, 0x55, 0x55, 0x55, 0x55, 0x44, 0x44, 0x44, 0x44, 0x5d, 0x55, 0x55, 0x47, 0x44, 0x44, 0x44, - 0x5d, 0x55, 0x55, 0x4e, 0x44, 0x44, 0x44, 0x5e, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, - 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, - 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, - 0x55, 0x66, 0x66, 0x66, 0x66, 0x5e, 0x55, 0x55, 0x68, 0x66, 0x66, 0x66, 0x57, 0x55, 0x55, 0x64, - 0x66, 0x66, 0x66, 0x54, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, - 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, - 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x66, 0x66, 0x66, - 0x66, 0x5e, 0x55, 0x55, 0x68, 0x66, 0x66, 0x66, 0x57, 0x55, 0x55, 0x64, 0x66, 0x66, 0x66, 0x54, - 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, - 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, - 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x66, 0x66, 0x66, 0x66, 0x5e, 0x55, 0x55, - 0x68, 0x66, 0x66, 0x66, 0x57, 0x55, 0x55, 0x64, 0x66, 0x66, 0x66, 0x54, 0x55, 0x55, 0x55, 0x55, - 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, - 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, - 0x55, 0x55, 0x55, 0x55, 0x55, 0x67, 0x66, 0x66, 0x66, 0x5e, 0x55, 0x55, 0x68, 0x66, 0x66, 0x66, - 0x57, 0x55, 0x55, 0x64, 0x66, 0x66, 0x66, 0x5d, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, - 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, - 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, - 0x55, 0x60, 0x66, 0x66, 0x66, 0x5e, 0x55, 0x55, 0x68, 0x66, 0x66, 0x66, 0x57, 0x55, 0x55, 0x64, - 0x66, 0x66, 0x66, 0x5b, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, - 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, - 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x79, 0x66, 0x66, - 0x66, 0x5e, 0x55, 0x55, 0x68, 0x66, 0x66, 0x66, 0x57, 0x55, 0x55, 0x64, 0x66, 0x66, 0x36, 0x55, - 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, - 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, - 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0xf5, 0x67, 0x66, 0x66, 0x5e, 0x55, 0x55, - 0x68, 0x66, 0x66, 0x66, 0x57, 0x55, 0x55, 0x64, 0x66, 0x66, 0x2e, 0x55, 0x55, 0x55, 0x55, 0x55, - 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, - 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, - 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x0c, 0x8e, 0x66, 0x5e, 0x55, 0x55, 0x68, 0x66, 0x66, 0x66, - 0x57, 0x55, 0x55, 0x64, 0x86, 0xb3, 0x5c, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, - 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, - 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, - 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, - 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, - 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, - 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, - 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, - 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, - 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, - 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, - 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, - 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, - 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, - 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, - 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, - 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, - 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, - 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, - 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, - 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, - 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, - 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, - 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, - 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, - 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, - 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, - 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, - 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, - 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, - 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, - 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, - 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x33, 0x55, 0x55, - 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, - 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x65, 0x51, 0x55, 0x55, 0x55, 0x55, 0x55, - 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0xab, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, - 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x33, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, - 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x3b, 0x33, - 0x33, 0x33, 0xb0, 0x55, 0x55, 0x65, 0x51, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, - 0x55, 0x55, 0x55, 0x55, 0x30, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, - 0x55, 0x55, 0x55, 0x55, 0x55, 0x33, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, - 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x40, 0x00, 0x00, 0x00, 0x6d, 0x14, - 0x55, 0x65, 0x51, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, - 0x30, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, - 0x55, 0x33, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, - 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x30, 0x55, 0x55, 0x55, 0xf5, 0x87, 0x59, 0x65, 0x51, 0x55, - 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x30, 0x55, 0x55, 0x55, - 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x33, 0x55, 0x55, - 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, - 0x55, 0x55, 0x30, 0x55, 0x55, 0x55, 0x55, 0x69, 0x50, 0x65, 0x51, 0x55, 0x55, 0x55, 0x55, 0x55, - 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x30, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, - 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x33, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, - 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x30, 0x55, - 0x55, 0x55, 0x55, 0x35, 0x5d, 0x65, 0x51, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, - 0x55, 0x55, 0x55, 0x55, 0x30, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x40, 0x66, 0xd6, 0x51, 0x55, - 0x55, 0x7b, 0x66, 0x46, 0x50, 0x3a, 0x55, 0x15, 0x6d, 0x66, 0x38, 0x33, 0xb3, 0x55, 0xd1, 0x66, - 0x46, 0x50, 0x55, 0x35, 0x95, 0x6a, 0x66, 0x50, 0x55, 0x55, 0x30, 0x55, 0x55, 0x55, 0x55, 0x35, - 0x53, 0x65, 0x51, 0x31, 0x55, 0x55, 0x55, 0x55, 0x31, 0x55, 0x55, 0xa9, 0x68, 0x86, 0x9a, 0x55, - 0x30, 0x55, 0x55, 0x55, 0x55, 0x55, 0x79, 0xb4, 0x5f, 0xd1, 0x18, 0x55, 0xa5, 0x06, 0x51, 0xbf, - 0xa7, 0x30, 0x55, 0x81, 0x90, 0x55, 0x71, 0x18, 0x51, 0xb5, 0xa6, 0x51, 0xb9, 0xa8, 0x55, 0x65, - 0x79, 0x1d, 0x15, 0x59, 0x55, 0x55, 0x30, 0x55, 0x55, 0x55, 0x55, 0x85, 0x50, 0x65, 0x51, 0x61, - 0x55, 0x55, 0x55, 0x55, 0x61, 0x55, 0x15, 0x38, 0x9b, 0xb5, 0x77, 0x59, 0x30, 0x55, 0x55, 0x55, - 0x55, 0x55, 0x7a, 0x59, 0x55, 0x55, 0x4d, 0x55, 0x6b, 0x5b, 0x55, 0x55, 0x75, 0x34, 0x55, 0xa3, - 0x55, 0x55, 0x95, 0xb8, 0x55, 0x6f, 0x5b, 0x55, 0x55, 0x61, 0x5b, 0x65, 0x03, 0x55, 0x55, 0x55, - 0x55, 0x55, 0x30, 0x55, 0x55, 0x55, 0x55, 0x8a, 0x59, 0x65, 0x51, 0x61, 0x55, 0x55, 0x55, 0x55, - 0x61, 0x55, 0x45, 0x5a, 0x55, 0x55, 0x49, 0x5a, 0x30, 0x55, 0x55, 0x55, 0x55, 0x15, 0x16, 0x55, - 0x55, 0x55, 0x6f, 0x5b, 0xa7, 0x55, 0x55, 0x55, 0x15, 0x36, 0xf5, 0x16, 0x55, 0x55, 0x55, 0xda, - 0x55, 0x3d, 0x55, 0x55, 0x55, 0xa5, 0x57, 0x65, 0x54, 0x55, 0x55, 0x55, 0x55, 0x55, 0x70, 0x11, - 0x11, 0x11, 0x70, 0x13, 0x55, 0x65, 0x51, 0x61, 0x55, 0x55, 0x55, 0x55, 0x61, 0x55, 0x80, 0x59, - 0x55, 0x55, 0xb5, 0x96, 0x30, 0x55, 0x55, 0x55, 0x55, 0xa5, 0x54, 0x55, 0x55, 0x55, 0x75, 0xfa, - 0xb6, 0x55, 0x55, 0x55, 0x55, 0x38, 0x15, 0x56, 0x55, 0x55, 0x55, 0x30, 0x95, 0xb6, 0x55, 0x55, - 0x55, 0xb5, 0x96, 0x65, 0x50, 0x55, 0x55, 0x55, 0x55, 0x55, 0x60, 0x66, 0x66, 0x66, 0xa8, 0x5f, - 0x55, 0x65, 0x51, 0x61, 0x55, 0x55, 0x55, 0x55, 0x61, 0x55, 0xa7, 0x55, 0x55, 0x55, 0x95, 0xb6, - 0x30, 0x55, 0x55, 0x55, 0x55, 0x35, 0x5a, 0x55, 0x55, 0x55, 0x35, 0x13, 0x96, 0x55, 0x55, 0x55, - 0x55, 0x33, 0x15, 0x16, 0x55, 0x55, 0x55, 0x3a, 0x15, 0xf6, 0x55, 0x55, 0x55, 0x15, 0x16, 0x65, - 0x51, 0x55, 0x55, 0x55, 0x55, 0x55, 0x30, 0x55, 0x55, 0x55, 0xa1, 0xa8, 0x55, 0x65, 0x51, 0x61, - 0x55, 0x55, 0x55, 0x55, 0x61, 0x55, 0xb6, 0x55, 0x55, 0x55, 0x55, 0x06, 0x30, 0x55, 0x55, 0x55, - 0x55, 0x85, 0x34, 0x33, 0x33, 0x33, 0x43, 0x03, 0x56, 0x55, 0x55, 0x55, 0x55, 0x33, 0x55, 0x04, - 0x55, 0x55, 0x95, 0xb4, 0x05, 0x36, 0x33, 0x33, 0x33, 0x33, 0x16, 0x65, 0x51, 0x55, 0x55, 0x55, - 0x55, 0x55, 0x30, 0x55, 0x55, 0x55, 0x55, 0x81, 0x5a, 0x65, 0x51, 0x61, 0x55, 0x55, 0x55, 0x55, - 0x61, 0x15, 0x76, 0x33, 0x33, 0x33, 0x33, 0x08, 0x30, 0x55, 0x55, 0x55, 0x55, 0x65, 0x03, 0x00, - 0x00, 0x00, 0x00, 0x0b, 0x56, 0x55, 0x55, 0x55, 0x55, 0x33, 0x55, 0x6b, 0x90, 0x55, 0x7f, 0x53, - 0x05, 0x06, 0x00, 0x00, 0x00, 0x00, 0xf0, 0x65, 0x51, 0x55, 0x55, 0x55, 0x55, 0x55, 0x30, 0x55, - 0x55, 0x55, 0x55, 0xa5, 0x58, 0x65, 0x51, 0x61, 0x55, 0x55, 0x55, 0x55, 0x61, 0x15, 0xa6, 0x00, - 0x00, 0x00, 0x00, 0x10, 0x30, 0x55, 0x55, 0x55, 0x55, 0x45, 0x50, 0x55, 0x55, 0x55, 0x55, 0x05, - 0x56, 0x55, 0x55, 0x55, 0x55, 0x33, 0x55, 0x15, 0x68, 0x64, 0x08, 0x55, 0xb5, 0x56, 0x55, 0x55, - 0x55, 0x55, 0x55, 0x65, 0x51, 0x55, 0x55, 0x55, 0x55, 0x55, 0x30, 0x55, 0x55, 0x55, 0x55, 0x15, - 0x16, 0x65, 0x51, 0x61, 0x55, 0x55, 0x55, 0x55, 0x61, 0xf5, 0x16, 0x55, 0x55, 0x55, 0x55, 0x55, - 0x30, 0x55, 0x55, 0x55, 0x55, 0x35, 0x5a, 0x55, 0x55, 0x55, 0x55, 0x15, 0x96, 0x55, 0x55, 0x55, - 0x55, 0x33, 0x55, 0xa5, 0xfa, 0x91, 0x55, 0x55, 0x15, 0xf6, 0x55, 0x55, 0x55, 0x55, 0x55, 0x65, - 0x51, 0x55, 0x55, 0x55, 0x55, 0x55, 0x30, 0x55, 0x55, 0x55, 0x55, 0x15, 0x16, 0x65, 0x51, 0x61, - 0x55, 0x55, 0x55, 0x55, 0x6b, 0x55, 0xb6, 0x55, 0x55, 0x55, 0x55, 0x55, 0x30, 0x55, 0x55, 0x55, - 0x55, 0x05, 0x58, 0x55, 0x55, 0x55, 0x55, 0x95, 0xb6, 0x55, 0x55, 0x55, 0x55, 0x38, 0x55, 0x41, - 0x55, 0x55, 0x55, 0x55, 0x55, 0x08, 0x55, 0x55, 0x55, 0x55, 0x55, 0x65, 0x51, 0x55, 0x55, 0x55, - 0x55, 0x55, 0x30, 0x55, 0x55, 0x55, 0x55, 0x05, 0x56, 0x65, 0x51, 0x61, 0x59, 0x55, 0x55, 0x55, - 0x6a, 0x55, 0xdd, 0x55, 0x55, 0x55, 0x55, 0x55, 0x30, 0x55, 0x55, 0x55, 0x55, 0xf5, 0x06, 0x55, - 0x55, 0x55, 0x55, 0x55, 0x33, 0x55, 0x55, 0x55, 0xb5, 0x36, 0x55, 0x70, 0x55, 0x55, 0x55, 0x55, - 0x55, 0x4a, 0x59, 0x55, 0x55, 0x55, 0x55, 0x65, 0x51, 0x55, 0x55, 0x55, 0x55, 0x55, 0x30, 0x55, - 0x55, 0x55, 0x55, 0x89, 0x5a, 0x65, 0x51, 0x65, 0x5b, 0x55, 0x55, 0x95, 0x64, 0x55, 0x6b, 0x51, - 0x55, 0x55, 0x55, 0x55, 0x30, 0x55, 0x55, 0x55, 0x55, 0x55, 0x60, 0x5b, 0x55, 0x55, 0x95, 0x59, - 0x61, 0x5a, 0x55, 0x55, 0x81, 0x33, 0x55, 0x89, 0x03, 0x00, 0x00, 0x51, 0x55, 0x49, 0x97, 0x55, - 0x55, 0x55, 0x5f, 0x65, 0x51, 0x55, 0x55, 0x55, 0x55, 0x55, 0x30, 0x55, 0x55, 0x55, 0x15, 0x77, - 0x59, 0x65, 0x51, 0xa5, 0x97, 0x55, 0x55, 0xa9, 0x67, 0x55, 0xd5, 0x18, 0x55, 0x55, 0x55, 0x5f, - 0x80, 0x33, 0x33, 0x33, 0x33, 0x53, 0x05, 0x76, 0x00, 0x00, 0x63, 0x51, 0xb5, 0x48, 0x00, 0xa0, - 0xb8, 0x3b, 0x55, 0xdf, 0x36, 0x33, 0x83, 0x46, 0x51, 0x15, 0x87, 0x0a, 0x00, 0x4a, 0x53, 0x65, - 0x51, 0x55, 0x55, 0x55, 0x55, 0x55, 0x80, 0x33, 0x33, 0x33, 0x68, 0x9a, 0x55, 0x65, 0x51, 0x95, - 0x87, 0x0a, 0xa0, 0xd8, 0x6b, 0x55, 0x95, 0x6d, 0x0d, 0x00, 0x7a, 0x56, 0x01, 0x00, 0x00, 0x00, - 0x00, 0x50, 0x55, 0x0f, 0x33, 0xd3, 0xf0, 0x55, 0x55, 0x09, 0x3d, 0x03, 0x5f, 0xbf, 0xb5, 0x18, - 0x55, 0x55, 0x55, 0x3f, 0x98, 0x55, 0xb5, 0x3a, 0x33, 0xba, 0x55, 0x05, 0x5f, 0x55, 0x55, 0x55, - 0x55, 0x55, 0x01, 0x00, 0x00, 0x00, 0x9b, 0x55, 0x55, 0x05, 0x5f, 0x55, 0x09, 0x3d, 0xa3, 0x51, - 0x09, 0x55, 0x55, 0x15, 0x3a, 0x33, 0xba, 0x59, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, - 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x6f, 0x51, 0x55, 0x55, 0x55, 0x95, - 0x16, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, - 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, - 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, - 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x6b, 0x55, 0x55, 0x55, 0x55, 0x55, 0x16, 0x55, 0x55, 0x55, - 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, - 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, - 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, - 0x55, 0x55, 0x6b, 0x55, 0x55, 0x55, 0x55, 0x15, 0x16, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, - 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, - 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, - 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x6f, 0x50, - 0x55, 0x55, 0x55, 0x79, 0x53, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, - 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, - 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, - 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0xb5, 0xa6, 0x1b, 0x11, 0xa1, 0x38, - 0x59, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, - 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, - 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, - 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0xa1, 0x67, 0x66, 0xa7, 0x51, 0x55, 0x55, 0x55, 0x55, - 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, - 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, + 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, + 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x09, 0x87, 0x66, 0x5e, 0x55, 0x55, 0x68, 0x66, 0x66, 0x66, + 0x66, 0x66, 0x66, 0x66, 0x86, 0xbe, 0x5c, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, + 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, + 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, + 0x55, 0xf5, 0x64, 0x66, 0x66, 0x5e, 0x55, 0x55, 0x68, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, + 0x66, 0x66, 0x27, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, + 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, + 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x49, 0x66, 0x66, + 0x66, 0x5e, 0x55, 0x55, 0x68, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0xe6, 0x5c, + 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, + 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, + 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x60, 0x66, 0x66, 0x66, 0x5e, 0x55, 0x55, + 0x68, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x5b, 0x55, 0x55, 0x55, 0x55, + 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, + 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, + 0x55, 0x55, 0x55, 0x55, 0x55, 0x67, 0x66, 0x66, 0x66, 0x5e, 0x55, 0x55, 0x68, 0x66, 0x66, 0x66, + 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x5d, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, + 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, + 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, + 0x55, 0x66, 0x66, 0x66, 0x66, 0x5e, 0x55, 0x55, 0x68, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, + 0x66, 0x66, 0x66, 0x54, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, + 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, + 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x66, 0x66, 0x66, + 0x66, 0x5e, 0x55, 0x55, 0x68, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x54, + 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, + 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, + 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x66, 0x66, 0x66, 0x66, 0x5e, 0x55, 0x55, + 0x68, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x54, 0x55, 0x55, 0x55, 0x55, + 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, + 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, + 0x55, 0x55, 0x55, 0x55, 0x55, 0x77, 0x77, 0x77, 0x77, 0x5a, 0x55, 0x55, 0x68, 0x66, 0x66, 0x66, + 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x54, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, + 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, + 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, + 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x68, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, + 0x66, 0x66, 0x66, 0x54, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, + 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, + 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, + 0x55, 0x55, 0x55, 0x55, 0x68, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x54, + 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, + 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, + 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, + 0x68, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x54, 0x55, 0x55, 0x55, 0x55, + 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, + 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, + 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x68, 0x66, 0x66, 0x66, + 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x54, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, + 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, + 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, + 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x68, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, + 0x66, 0x66, 0x66, 0x54, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, + 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, + 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x88, 0x88, 0x88, + 0x88, 0x5d, 0x55, 0x55, 0x68, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x54, + 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, + 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, + 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x66, 0x66, 0x66, 0x66, 0x5e, 0x55, 0x55, + 0x68, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x54, 0x55, 0x55, 0x55, 0x55, + 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, + 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, + 0x55, 0x55, 0x55, 0x55, 0x55, 0x66, 0x66, 0x66, 0x66, 0x5e, 0x55, 0x55, 0x68, 0x66, 0x66, 0x66, + 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x54, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, + 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, + 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, + 0x55, 0x66, 0x66, 0x66, 0x66, 0x5e, 0x55, 0x55, 0x68, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, + 0x66, 0x66, 0x66, 0x54, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, + 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, + 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x66, 0x66, 0x66, + 0x66, 0x5e, 0x55, 0x55, 0x68, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x54, + 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, + 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, + 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x66, 0x66, 0x66, 0x66, 0x5e, 0x55, 0x55, + 0x68, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x54, 0x55, 0x55, 0x55, 0x55, + 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, + 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, + 0x55, 0x55, 0x55, 0x55, 0x55, 0x66, 0x66, 0x66, 0x66, 0x5e, 0x55, 0x55, 0x68, 0x66, 0x66, 0x66, + 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x54, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, + 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, + 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, + 0x55, 0x66, 0x66, 0x66, 0x66, 0x5e, 0x55, 0x55, 0x68, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, + 0x66, 0x66, 0x66, 0x54, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, + 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, + 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x44, 0x44, 0x44, + 0x44, 0x5d, 0x55, 0x55, 0x47, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x5e, + 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, + 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, + 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, + 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, + 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, + 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, + 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, + 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, + 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, + 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, + 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, + 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, + 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, + 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, + 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, + 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, + 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, + 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, + 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, + 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, + 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, + 0x55, 0x55, 0x55, 0x55, 0x55, 0x44, 0x44, 0x44, 0x44, 0x5d, 0x55, 0x55, 0x47, 0x44, 0x44, 0x44, + 0x5d, 0x55, 0x55, 0x4e, 0x44, 0x44, 0x44, 0x5e, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, + 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, + 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, + 0x55, 0x66, 0x66, 0x66, 0x66, 0x5e, 0x55, 0x55, 0x68, 0x66, 0x66, 0x66, 0x57, 0x55, 0x55, 0x64, + 0x66, 0x66, 0x66, 0x54, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, + 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, + 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x66, 0x66, 0x66, + 0x66, 0x5e, 0x55, 0x55, 0x68, 0x66, 0x66, 0x66, 0x57, 0x55, 0x55, 0x64, 0x66, 0x66, 0x66, 0x54, + 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, + 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, + 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x66, 0x66, 0x66, 0x66, 0x5e, 0x55, 0x55, + 0x68, 0x66, 0x66, 0x66, 0x57, 0x55, 0x55, 0x64, 0x66, 0x66, 0x66, 0x54, 0x55, 0x55, 0x55, 0x55, + 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, + 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, + 0x55, 0x55, 0x55, 0x55, 0x55, 0x67, 0x66, 0x66, 0x66, 0x5e, 0x55, 0x55, 0x68, 0x66, 0x66, 0x66, + 0x57, 0x55, 0x55, 0x64, 0x66, 0x66, 0x66, 0x5d, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, + 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, + 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, + 0x55, 0x60, 0x66, 0x66, 0x66, 0x5e, 0x55, 0x55, 0x68, 0x66, 0x66, 0x66, 0x57, 0x55, 0x55, 0x64, + 0x66, 0x66, 0x66, 0x5b, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, + 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, + 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x79, 0x66, 0x66, + 0x66, 0x5e, 0x55, 0x55, 0x68, 0x66, 0x66, 0x66, 0x57, 0x55, 0x55, 0x64, 0x66, 0x66, 0x36, 0x55, + 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, + 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, + 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0xf5, 0x67, 0x66, 0x66, 0x5e, 0x55, 0x55, + 0x68, 0x66, 0x66, 0x66, 0x57, 0x55, 0x55, 0x64, 0x66, 0x66, 0x2e, 0x55, 0x55, 0x55, 0x55, 0x55, + 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, + 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, + 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x0c, 0x8e, 0x66, 0x5e, 0x55, 0x55, 0x68, 0x66, 0x66, 0x66, + 0x57, 0x55, 0x55, 0x64, 0x86, 0xb3, 0x5c, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, + 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, + 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, + 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, + 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, + 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, + 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, + 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, + 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, + 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, + 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, + 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, + 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, + 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, + 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, + 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, + 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, + 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, + 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, + 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, + 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, + 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, + 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, + 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, + 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, + 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, + 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, + 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, + 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, + 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, + 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, + 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, + 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x33, 0x55, 0x55, + 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, + 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x65, 0x51, 0x55, 0x55, 0x55, 0x55, 0x55, + 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0xab, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, + 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x33, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, + 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x3b, 0x33, + 0x33, 0x33, 0xb0, 0x55, 0x55, 0x65, 0x51, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, + 0x55, 0x55, 0x55, 0x55, 0x30, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, + 0x55, 0x55, 0x55, 0x55, 0x55, 0x33, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, + 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x40, 0x00, 0x00, 0x00, 0x6d, 0x14, + 0x55, 0x65, 0x51, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, + 0x30, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, + 0x55, 0x33, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, + 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x30, 0x55, 0x55, 0x55, 0xf5, 0x87, 0x59, 0x65, 0x51, 0x55, + 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x30, 0x55, 0x55, 0x55, + 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x33, 0x55, 0x55, + 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, + 0x55, 0x55, 0x30, 0x55, 0x55, 0x55, 0x55, 0x69, 0x50, 0x65, 0x51, 0x55, 0x55, 0x55, 0x55, 0x55, + 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x30, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, + 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x33, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, + 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x30, 0x55, + 0x55, 0x55, 0x55, 0x35, 0x5d, 0x65, 0x51, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, + 0x55, 0x55, 0x55, 0x55, 0x30, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x40, 0x66, 0xd6, 0x51, 0x55, + 0x55, 0x7b, 0x66, 0x46, 0x50, 0x3a, 0x55, 0x15, 0x6d, 0x66, 0x38, 0x33, 0xb3, 0x55, 0xd1, 0x66, + 0x46, 0x50, 0x55, 0x35, 0x95, 0x6a, 0x66, 0x50, 0x55, 0x55, 0x30, 0x55, 0x55, 0x55, 0x55, 0x35, + 0x53, 0x65, 0x51, 0x31, 0x55, 0x55, 0x55, 0x55, 0x31, 0x55, 0x55, 0xa9, 0x68, 0x86, 0x9a, 0x55, + 0x30, 0x55, 0x55, 0x55, 0x55, 0x55, 0x79, 0xb4, 0x5f, 0xd1, 0x18, 0x55, 0xa5, 0x06, 0x51, 0xbf, + 0xa7, 0x30, 0x55, 0x81, 0x90, 0x55, 0x71, 0x18, 0x51, 0xb5, 0xa6, 0x51, 0xb9, 0xa8, 0x55, 0x65, + 0x79, 0x1d, 0x15, 0x59, 0x55, 0x55, 0x30, 0x55, 0x55, 0x55, 0x55, 0x85, 0x50, 0x65, 0x51, 0x61, + 0x55, 0x55, 0x55, 0x55, 0x61, 0x55, 0x15, 0x38, 0x9b, 0xb5, 0x77, 0x59, 0x30, 0x55, 0x55, 0x55, + 0x55, 0x55, 0x7a, 0x59, 0x55, 0x55, 0x4d, 0x55, 0x6b, 0x5b, 0x55, 0x55, 0x75, 0x34, 0x55, 0xa3, + 0x55, 0x55, 0x95, 0xb8, 0x55, 0x6f, 0x5b, 0x55, 0x55, 0x61, 0x5b, 0x65, 0x03, 0x55, 0x55, 0x55, + 0x55, 0x55, 0x30, 0x55, 0x55, 0x55, 0x55, 0x8a, 0x59, 0x65, 0x51, 0x61, 0x55, 0x55, 0x55, 0x55, + 0x61, 0x55, 0x45, 0x5a, 0x55, 0x55, 0x49, 0x5a, 0x30, 0x55, 0x55, 0x55, 0x55, 0x15, 0x16, 0x55, + 0x55, 0x55, 0x6f, 0x5b, 0xa7, 0x55, 0x55, 0x55, 0x15, 0x36, 0xf5, 0x16, 0x55, 0x55, 0x55, 0xda, + 0x55, 0x3d, 0x55, 0x55, 0x55, 0xa5, 0x57, 0x65, 0x54, 0x55, 0x55, 0x55, 0x55, 0x55, 0x70, 0x11, + 0x11, 0x11, 0x70, 0x13, 0x55, 0x65, 0x51, 0x61, 0x55, 0x55, 0x55, 0x55, 0x61, 0x55, 0x80, 0x59, + 0x55, 0x55, 0xb5, 0x96, 0x30, 0x55, 0x55, 0x55, 0x55, 0xa5, 0x54, 0x55, 0x55, 0x55, 0x75, 0xfa, + 0xb6, 0x55, 0x55, 0x55, 0x55, 0x38, 0x15, 0x56, 0x55, 0x55, 0x55, 0x30, 0x95, 0xb6, 0x55, 0x55, + 0x55, 0xb5, 0x96, 0x65, 0x50, 0x55, 0x55, 0x55, 0x55, 0x55, 0x60, 0x66, 0x66, 0x66, 0xa8, 0x5f, + 0x55, 0x65, 0x51, 0x61, 0x55, 0x55, 0x55, 0x55, 0x61, 0x55, 0xa7, 0x55, 0x55, 0x55, 0x95, 0xb6, + 0x30, 0x55, 0x55, 0x55, 0x55, 0x35, 0x5a, 0x55, 0x55, 0x55, 0x35, 0x13, 0x96, 0x55, 0x55, 0x55, + 0x55, 0x33, 0x15, 0x16, 0x55, 0x55, 0x55, 0x3a, 0x15, 0xf6, 0x55, 0x55, 0x55, 0x15, 0x16, 0x65, + 0x51, 0x55, 0x55, 0x55, 0x55, 0x55, 0x30, 0x55, 0x55, 0x55, 0xa1, 0xa8, 0x55, 0x65, 0x51, 0x61, + 0x55, 0x55, 0x55, 0x55, 0x61, 0x55, 0xb6, 0x55, 0x55, 0x55, 0x55, 0x06, 0x30, 0x55, 0x55, 0x55, + 0x55, 0x85, 0x34, 0x33, 0x33, 0x33, 0x43, 0x03, 0x56, 0x55, 0x55, 0x55, 0x55, 0x33, 0x55, 0x04, + 0x55, 0x55, 0x95, 0xb4, 0x05, 0x36, 0x33, 0x33, 0x33, 0x33, 0x16, 0x65, 0x51, 0x55, 0x55, 0x55, + 0x55, 0x55, 0x30, 0x55, 0x55, 0x55, 0x55, 0x81, 0x5a, 0x65, 0x51, 0x61, 0x55, 0x55, 0x55, 0x55, + 0x61, 0x15, 0x76, 0x33, 0x33, 0x33, 0x33, 0x08, 0x30, 0x55, 0x55, 0x55, 0x55, 0x65, 0x03, 0x00, + 0x00, 0x00, 0x00, 0x0b, 0x56, 0x55, 0x55, 0x55, 0x55, 0x33, 0x55, 0x6b, 0x90, 0x55, 0x7f, 0x53, + 0x05, 0x06, 0x00, 0x00, 0x00, 0x00, 0xf0, 0x65, 0x51, 0x55, 0x55, 0x55, 0x55, 0x55, 0x30, 0x55, + 0x55, 0x55, 0x55, 0xa5, 0x58, 0x65, 0x51, 0x61, 0x55, 0x55, 0x55, 0x55, 0x61, 0x15, 0xa6, 0x00, + 0x00, 0x00, 0x00, 0x10, 0x30, 0x55, 0x55, 0x55, 0x55, 0x45, 0x50, 0x55, 0x55, 0x55, 0x55, 0x05, + 0x56, 0x55, 0x55, 0x55, 0x55, 0x33, 0x55, 0x15, 0x68, 0x64, 0x08, 0x55, 0xb5, 0x56, 0x55, 0x55, + 0x55, 0x55, 0x55, 0x65, 0x51, 0x55, 0x55, 0x55, 0x55, 0x55, 0x30, 0x55, 0x55, 0x55, 0x55, 0x15, + 0x16, 0x65, 0x51, 0x61, 0x55, 0x55, 0x55, 0x55, 0x61, 0xf5, 0x16, 0x55, 0x55, 0x55, 0x55, 0x55, + 0x30, 0x55, 0x55, 0x55, 0x55, 0x35, 0x5a, 0x55, 0x55, 0x55, 0x55, 0x15, 0x96, 0x55, 0x55, 0x55, + 0x55, 0x33, 0x55, 0xa5, 0xfa, 0x91, 0x55, 0x55, 0x15, 0xf6, 0x55, 0x55, 0x55, 0x55, 0x55, 0x65, + 0x51, 0x55, 0x55, 0x55, 0x55, 0x55, 0x30, 0x55, 0x55, 0x55, 0x55, 0x15, 0x16, 0x65, 0x51, 0x61, + 0x55, 0x55, 0x55, 0x55, 0x6b, 0x55, 0xb6, 0x55, 0x55, 0x55, 0x55, 0x55, 0x30, 0x55, 0x55, 0x55, + 0x55, 0x05, 0x58, 0x55, 0x55, 0x55, 0x55, 0x95, 0xb6, 0x55, 0x55, 0x55, 0x55, 0x38, 0x55, 0x41, + 0x55, 0x55, 0x55, 0x55, 0x55, 0x08, 0x55, 0x55, 0x55, 0x55, 0x55, 0x65, 0x51, 0x55, 0x55, 0x55, + 0x55, 0x55, 0x30, 0x55, 0x55, 0x55, 0x55, 0x05, 0x56, 0x65, 0x51, 0x61, 0x59, 0x55, 0x55, 0x55, + 0x6a, 0x55, 0xdd, 0x55, 0x55, 0x55, 0x55, 0x55, 0x30, 0x55, 0x55, 0x55, 0x55, 0xf5, 0x06, 0x55, + 0x55, 0x55, 0x55, 0x55, 0x33, 0x55, 0x55, 0x55, 0xb5, 0x36, 0x55, 0x70, 0x55, 0x55, 0x55, 0x55, + 0x55, 0x4a, 0x59, 0x55, 0x55, 0x55, 0x55, 0x65, 0x51, 0x55, 0x55, 0x55, 0x55, 0x55, 0x30, 0x55, + 0x55, 0x55, 0x55, 0x89, 0x5a, 0x65, 0x51, 0x65, 0x5b, 0x55, 0x55, 0x95, 0x64, 0x55, 0x6b, 0x51, + 0x55, 0x55, 0x55, 0x55, 0x30, 0x55, 0x55, 0x55, 0x55, 0x55, 0x60, 0x5b, 0x55, 0x55, 0x95, 0x59, + 0x61, 0x5a, 0x55, 0x55, 0x81, 0x33, 0x55, 0x89, 0x03, 0x00, 0x00, 0x51, 0x55, 0x49, 0x97, 0x55, + 0x55, 0x55, 0x5f, 0x65, 0x51, 0x55, 0x55, 0x55, 0x55, 0x55, 0x30, 0x55, 0x55, 0x55, 0x15, 0x77, + 0x59, 0x65, 0x51, 0xa5, 0x97, 0x55, 0x55, 0xa9, 0x67, 0x55, 0xd5, 0x18, 0x55, 0x55, 0x55, 0x5f, + 0x80, 0x33, 0x33, 0x33, 0x33, 0x53, 0x05, 0x76, 0x00, 0x00, 0x63, 0x51, 0xb5, 0x48, 0x00, 0xa0, + 0xb8, 0x3b, 0x55, 0xdf, 0x36, 0x33, 0x83, 0x46, 0x51, 0x15, 0x87, 0x0a, 0x00, 0x4a, 0x53, 0x65, + 0x51, 0x55, 0x55, 0x55, 0x55, 0x55, 0x80, 0x33, 0x33, 0x33, 0x68, 0x9a, 0x55, 0x65, 0x51, 0x95, + 0x87, 0x0a, 0xa0, 0xd8, 0x6b, 0x55, 0x95, 0x6d, 0x0d, 0x00, 0x7a, 0x56, 0x01, 0x00, 0x00, 0x00, + 0x00, 0x50, 0x55, 0x0f, 0x33, 0xd3, 0xf0, 0x55, 0x55, 0x09, 0x3d, 0x03, 0x5f, 0xbf, 0xb5, 0x18, + 0x55, 0x55, 0x55, 0x3f, 0x98, 0x55, 0xb5, 0x3a, 0x33, 0xba, 0x55, 0x05, 0x5f, 0x55, 0x55, 0x55, + 0x55, 0x55, 0x01, 0x00, 0x00, 0x00, 0x9b, 0x55, 0x55, 0x05, 0x5f, 0x55, 0x09, 0x3d, 0xa3, 0x51, + 0x09, 0x55, 0x55, 0x15, 0x3a, 0x33, 0xba, 0x59, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, + 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x6f, 0x51, 0x55, 0x55, 0x55, 0x95, + 0x16, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, + 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, + 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, + 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x6b, 0x55, 0x55, 0x55, 0x55, 0x55, 0x16, 0x55, 0x55, 0x55, + 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, + 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, + 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, + 0x55, 0x55, 0x6b, 0x55, 0x55, 0x55, 0x55, 0x15, 0x16, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, + 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, + 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, + 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x6f, 0x50, + 0x55, 0x55, 0x55, 0x79, 0x53, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, + 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, + 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, + 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0xb5, 0xa6, 0x1b, 0x11, 0xa1, 0x38, + 0x59, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, + 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, + 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, + 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0xa1, 0x67, 0x66, 0xa7, 0x51, 0x55, 0x55, 0x55, 0x55, + 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, + 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, }; unsigned int const C_icon_clear_colors[] = { - 0x00fdfdfd, - 0x00333746, - 0x00868891, - 0x00d4d5d8, + 0x00fdfdfd, + 0x00333746, + 0x00868891, + 0x00d4d5d8, }; unsigned char const C_icon_clear_bitmap[] = { - 0xf5, 0x55, 0x55, 0x5b, 0x0d, 0x54, 0x15, 0x70, 0x03, 0x50, 0x05, 0x80, 0x00, 0x40, 0x01, 0xc0, - 0x02, 0x00, 0x00, 0x40, 0x09, 0x00, 0x00, 0x50, 0x25, 0x00, 0x00, 0x54, 0x95, 0x00, 0x00, 0x55, - 0x55, 0x00, 0x00, 0x55, 0x15, 0x00, 0x00, 0x54, 0x05, 0x00, 0x00, 0x50, 0x01, 0x00, 0x00, 0x40, - 0x00, 0x40, 0x02, 0xc0, 0x03, 0x50, 0x09, 0xc0, 0x0d, 0x54, 0x25, 0x70, 0x35, 0x55, 0x95, 0x5c, + 0xf5, 0x55, 0x55, 0x5b, 0x0d, 0x54, 0x15, 0x70, 0x03, 0x50, 0x05, 0x80, 0x00, 0x40, 0x01, 0xc0, + 0x02, 0x00, 0x00, 0x40, 0x09, 0x00, 0x00, 0x50, 0x25, 0x00, 0x00, 0x54, 0x95, 0x00, 0x00, 0x55, + 0x55, 0x00, 0x00, 0x55, 0x15, 0x00, 0x00, 0x54, 0x05, 0x00, 0x00, 0x50, 0x01, 0x00, 0x00, 0x40, + 0x00, 0x40, 0x02, 0xc0, 0x03, 0x50, 0x09, 0xc0, 0x0d, 0x54, 0x25, 0x70, 0x35, 0x55, 0x95, 0x5c, }; unsigned int const C_icon_backspace_colors[] = { - 0x00ffffff, - 0x00d3d4d7, - 0x008b8d95, - 0x0071737d, + 0x00ffffff, + 0x00d3d4d7, + 0x008b8d95, + 0x0071737d, }; unsigned char const C_icon_backspace_bitmap[] = { - 0xff, 0x07, 0x00, 0x00, 0x90, 0xff, 0x01, 0x00, 0x00, 0x40, 0x7f, 0x00, 0x00, 0x00, 0x00, 0x1f, - 0x00, 0x04, 0x14, 0x00, 0x07, 0x00, 0x1e, 0x3d, 0x00, 0x01, 0x00, 0x7d, 0x1f, 0x00, 0x00, 0x00, - 0xf4, 0x07, 0x00, 0x00, 0x00, 0xf4, 0x07, 0x00, 0x01, 0x00, 0x7d, 0x1f, 0x00, 0x07, 0x00, 0x1e, - 0x3d, 0x00, 0x1f, 0x00, 0x04, 0x14, 0x00, 0x7f, 0x00, 0x00, 0x00, 0x00, 0xff, 0x01, 0x00, 0x00, - 0x40, 0xff, 0x07, 0x00, 0x00, 0x90, + 0xff, 0x07, 0x00, 0x00, 0x90, 0xff, 0x01, 0x00, 0x00, 0x40, 0x7f, 0x00, 0x00, 0x00, + 0x00, 0x1f, 0x00, 0x04, 0x14, 0x00, 0x07, 0x00, 0x1e, 0x3d, 0x00, 0x01, 0x00, 0x7d, + 0x1f, 0x00, 0x00, 0x00, 0xf4, 0x07, 0x00, 0x00, 0x00, 0xf4, 0x07, 0x00, 0x01, 0x00, + 0x7d, 0x1f, 0x00, 0x07, 0x00, 0x1e, 0x3d, 0x00, 0x1f, 0x00, 0x04, 0x14, 0x00, 0x7f, + 0x00, 0x00, 0x00, 0x00, 0xff, 0x01, 0x00, 0x00, 0x40, 0xff, 0x07, 0x00, 0x00, 0x90, }; - unsigned int const C_icon_check_colors[] = { - 0x00000000, - 0x00ffffff, + 0x00000000, + 0x00ffffff, }; unsigned char const C_icon_check_bitmap[] = { - 0x80, 0x40, 0x20, 0x11, 0x0a, 0x04, + 0x80, + 0x40, + 0x20, + 0x11, + 0x0a, + 0x04, }; - unsigned int const C_icon_cross_colors[] = { - 0x00000000, - 0x00ffffff, + 0x00000000, + 0x00ffffff, }; unsigned char const C_icon_cross_bitmap[] = { - 0x41, 0x11, 0x05, 0x41, 0x11, 0x05, 0x01, + 0x41, + 0x11, + 0x05, + 0x41, + 0x11, + 0x05, + 0x01, }; unsigned int const C_icon_left_colors[] = { - 0x00000000, - 0x00ffffff, + 0x00000000, + 0x00ffffff, }; unsigned char const C_icon_left_bitmap[] = { - 0x48, 0x12, 0x42, 0x08, + 0x48, + 0x12, + 0x42, + 0x08, }; unsigned int const C_icon_right_colors[] = { - 0x00000000, - 0x00ffffff, + 0x00000000, + 0x00ffffff, }; unsigned char const C_icon_right_bitmap[] = { - 0x21, 0x84, 0x24, 0x01, + 0x21, + 0x84, + 0x24, + 0x01, }; - unsigned int const C_icon_up_colors[] = { - 0x00000000, - 0x00ffffff, + 0x00000000, + 0x00ffffff, }; unsigned char const C_icon_up_bitmap[] = { - 0x08, 0x8a, 0x28, 0x08, + 0x08, + 0x8a, + 0x28, + 0x08, }; unsigned int const C_icon_down_colors[] = { - 0x00000000, - 0x00ffffff, + 0x00000000, + 0x00ffffff, }; unsigned char const C_icon_down_bitmap[] = { - 0x41, 0x11, 0x05, 0x01, + 0x41, + 0x11, + 0x05, + 0x01, }; unsigned int const C_logo_ledger_mini_colors[] = { - 0x00ffffff, - 0x00000000, + 0x00ffffff, + 0x00000000, }; unsigned char const C_logo_ledger_mini_bitmap[] = { - 0x33, 0xc0, 0x31, 0x80, 0x30, 0x00, 0x30, 0x00, 0x3f, 0x00, 0x3f, 0x00, 0x30, 0x00, 0x30, 0x00, - 0x30, 0x00, 0x30, 0x00, 0xff, 0xff, 0xff, 0xff, 0x30, 0x0c, 0x30, 0x0c, 0x31, 0x8c, 0x33, 0xcc, + 0x33, 0xc0, 0x31, 0x80, 0x30, 0x00, 0x30, 0x00, 0x3f, 0x00, 0x3f, 0x00, 0x30, 0x00, 0x30, 0x00, + 0x30, 0x00, 0x30, 0x00, 0xff, 0xff, 0xff, 0xff, 0x30, 0x0c, 0x30, 0x0c, 0x31, 0x8c, 0x33, 0xcc, }; - unsigned int const C_icon_cross_badge_colors[] = { - 0x00ffffff, - 0x00000000, + 0x00ffffff, + 0x00000000, }; unsigned char const C_icon_cross_badge_bitmap[] = { - 0x1f, 0xfe, 0x01, 0x3e, 0x00, 0x47, 0x88, 0x39, 0x27, 0xfc, 0x00, 0x1e, 0x80, 0x07, 0xf0, 0x43, - 0xce, 0x19, 0x21, 0x0e, 0xc0, 0x07, 0xf8, 0x87, 0x0f, + 0x1f, 0xfe, 0x01, 0x3e, 0x00, 0x47, 0x88, 0x39, 0x27, 0xfc, 0x00, 0x1e, 0x80, + 0x07, 0xf0, 0x43, 0xce, 0x19, 0x21, 0x0e, 0xc0, 0x07, 0xf8, 0x87, 0x0f, }; - unsigned int const C_badge_dashboard_colors[] = { - 0x00ffffff, - 0x00000000, + 0x00ffffff, + 0x00000000, }; unsigned char const C_badge_dashboard_bitmap[] = { - 0x1f, 0xfe, 0x01, 0x3e, 0x00, 0xc7, 0x8f, 0xf9, 0x27, 0x86, 0x81, 0x61, 0x60, 0x18, 0x18, 0x46, - 0xfe, 0x19, 0x3f, 0x0e, 0xc0, 0x07, 0xf8, 0x87, 0x0f, + 0x1f, 0xfe, 0x01, 0x3e, 0x00, 0xc7, 0x8f, 0xf9, 0x27, 0x86, 0x81, 0x61, 0x60, + 0x18, 0x18, 0x46, 0xfe, 0x19, 0x3f, 0x0e, 0xc0, 0x07, 0xf8, 0x87, 0x0f, }; unsigned int const C_badge_validate_colors[] = { - 0x00ffffff, - 0x00000000, + 0x00ffffff, + 0x00000000, }; unsigned char const C_badge_validate_bitmap[] = { - 0x1f, 0xfe, 0x01, 0x3e, 0x00, 0x07, 0x80, 0x01, 0x24, 0x80, 0x83, 0x70, 0x70, 0x0e, 0xf8, 0x41, - 0x3c, 0x18, 0x06, 0x0e, 0xc0, 0x07, 0xf8, 0x87, 0x0f, + 0x1f, 0xfe, 0x01, 0x3e, 0x00, 0x07, 0x80, 0x01, 0x24, 0x80, 0x83, 0x70, 0x70, + 0x0e, 0xf8, 0x41, 0x3c, 0x18, 0x06, 0x0e, 0xc0, 0x07, 0xf8, 0x87, 0x0f, }; unsigned int const C_icon_plus_colors[] = { - 0x00000000, - 0x00ffffff, + 0x00000000, + 0x00ffffff, }; unsigned char const C_icon_plus_bitmap[] = { - 0x08, 0x04, 0xe2, 0x8f, 0x40, 0x20, 0x00, + 0x08, + 0x04, + 0xe2, + 0x8f, + 0x40, + 0x20, + 0x00, }; - unsigned int const C_icon_less_colors[] = { - 0x00000000, - 0x00ffffff, + 0x00000000, + 0x00ffffff, }; unsigned char const C_icon_less_bitmap[] = { - 0xff, + 0xff, }; - unsigned int const C_toggle_on_colors[] = { - 0x00000000, - 0x00ffffff, + 0x00000000, + 0x00ffffff, }; unsigned char const C_toggle_on_bitmap[] = { - 0xf8, 0x1f, 0x04, 0x20, 0x02, 0x4c, 0x01, 0x9e, 0x01, 0xbf, 0x01, 0xbf, 0x01, 0x9e, 0x02, 0x4c, - 0x04, 0x20, 0xf8, 0x1f, + 0xf8, 0x1f, 0x04, 0x20, 0x02, 0x4c, 0x01, 0x9e, 0x01, 0xbf, + 0x01, 0xbf, 0x01, 0x9e, 0x02, 0x4c, 0x04, 0x20, 0xf8, 0x1f, }; - unsigned int const C_toggle_off_colors[] = { - 0x00000000, - 0x00ffffff, + 0x00000000, + 0x00ffffff, }; unsigned char const C_toggle_off_bitmap[] = { - 0xf8, 0x1f, 0x04, 0x20, 0x32, 0x40, 0x79, 0x80, 0xfd, 0x80, 0xfd, 0x80, 0x79, 0x80, 0x32, 0x40, - 0x04, 0x20, 0xf8, 0x1f, + 0xf8, 0x1f, 0x04, 0x20, 0x32, 0x40, 0x79, 0x80, 0xfd, 0x80, + 0xfd, 0x80, 0x79, 0x80, 0x32, 0x40, 0x04, 0x20, 0xf8, 0x1f, }; unsigned int const C_badge_loading_colors[] = { - 0x00000000, - 0x00ffffff, + 0x00000000, + 0x00ffffff, }; unsigned char const C_badge_loading_bitmap[] = { - 0xc0, 0x00, 0x30, 0xc0, 0x00, 0x30, 0x00, 0x00, 0x00, 0x00, 0x30, 0x00, 0x0f, 0xc0, 0x00, 0x00, - 0x00, 0xc0, 0xc0, 0x30, 0x30, 0xc0, 0x00, 0x30, 0x00, + 0xc0, 0x00, 0x30, 0xc0, 0x00, 0x30, 0x00, 0x00, 0x00, 0x00, 0x30, 0x00, 0x0f, + 0xc0, 0x00, 0x00, 0x00, 0xc0, 0xc0, 0x30, 0x30, 0xc0, 0x00, 0x30, 0x00, }; unsigned int const C_app_settings_colors[] = { - 0x00000000, - 0x00ffffff, + 0x00000000, + 0x00ffffff, }; unsigned char const C_app_settings_bitmap[] = { - 0x00, 0x00, 0xf0, 0x0f, 0xfc, 0x3f, 0x7c, 0x3e, 0x5e, 0x7a, 0x0e, 0x70, 0x1e, 0x78, 0x86, 0x61, - 0x86, 0x61, 0x1e, 0x78, 0x0e, 0x70, 0x5e, 0x7a, 0x7c, 0x3e, 0xfc, 0x3f, 0xf0, 0x0f, 0x00, 0x00, + 0x00, 0x00, 0xf0, 0x0f, 0xfc, 0x3f, 0x7c, 0x3e, 0x5e, 0x7a, 0x0e, 0x70, 0x1e, 0x78, 0x86, 0x61, + 0x86, 0x61, 0x1e, 0x78, 0x0e, 0x70, 0x5e, 0x7a, 0x7c, 0x3e, 0xfc, 0x3f, 0xf0, 0x0f, 0x00, 0x00, }; - - unsigned int const C_badge_warning_colors[] = { - 0x00ffffff, - 0x00000000, + 0x00ffffff, + 0x00000000, }; unsigned char const C_badge_warning_bitmap[] = { - 0x1f, 0xfe, 0x01, 0x3e, 0x00, 0x07, 0x83, 0xc1, 0x20, 0x30, 0x00, 0x0c, 0x00, 0x03, 0x00, 0x40, - 0x30, 0x18, 0x0c, 0x0e, 0xc0, 0x07, 0xf8, 0x87, 0x0f, + 0x1f, 0xfe, 0x01, 0x3e, 0x00, 0x07, 0x83, 0xc1, 0x20, 0x30, 0x00, 0x0c, 0x00, + 0x03, 0x00, 0x40, 0x30, 0x18, 0x0c, 0x0e, 0xc0, 0x07, 0xf8, 0x87, 0x0f, }; - unsigned int const C_badge_install_colors[] = { - 0x00ffffff, - 0x00000000, + 0x00ffffff, + 0x00000000, }; unsigned char const C_badge_install_bitmap[] = { - 0x1f, 0xfe, 0x01, 0x3e, 0x0c, 0x07, 0x83, 0xc1, 0x20, 0xfc, 0x00, 0x1e, 0x00, 0x03, 0x00, 0x40, - 0xfc, 0x18, 0x3f, 0x0e, 0xc0, 0x07, 0xf8, 0x87, 0x0f, + 0x1f, 0xfe, 0x01, 0x3e, 0x0c, 0x07, 0x83, 0xc1, 0x20, 0xfc, 0x00, 0x1e, 0x00, + 0x03, 0x00, 0x40, 0xfc, 0x18, 0x3f, 0x0e, 0xc0, 0x07, 0xf8, 0x87, 0x0f, }; - unsigned int const C_badge_transaction_colors[] = { - 0x00ffffff, - 0x00000000, + 0x00ffffff, + 0x00000000, }; unsigned char const C_badge_transaction_bitmap[] = { - 0x1f, 0xfe, 0x01, 0x3e, 0x10, 0x07, 0x8c, 0xf9, 0x27, 0xfe, 0x01, 0x32, 0xc0, 0x04, 0xf8, 0x47, - 0xfe, 0x19, 0x03, 0x8e, 0xc0, 0x07, 0xf8, 0x87, 0x0f, + 0x1f, 0xfe, 0x01, 0x3e, 0x10, 0x07, 0x8c, 0xf9, 0x27, 0xfe, 0x01, 0x32, 0xc0, + 0x04, 0xf8, 0x47, 0xfe, 0x19, 0x03, 0x8e, 0xc0, 0x07, 0xf8, 0x87, 0x0f, }; unsigned int const C_badge_bitcoin_colors[] = { - 0x00ffffff, - 0x00000000, + 0x00ffffff, + 0x00000000, }; unsigned char const C_badge_bitcoin_bitmap[] = { - 0x1f, 0xfe, 0x01, 0x3e, 0x0a, 0xe7, 0x87, 0x31, 0x23, 0xcc, 0x00, 0x3f, 0xc0, 0x1c, 0x30, 0x46, - 0xcc, 0x99, 0x3f, 0x8e, 0xc2, 0x07, 0xf8, 0x87, 0x0f, + 0x1f, 0xfe, 0x01, 0x3e, 0x0a, 0xe7, 0x87, 0x31, 0x23, 0xcc, 0x00, 0x3f, 0xc0, + 0x1c, 0x30, 0x46, 0xcc, 0x99, 0x3f, 0x8e, 0xc2, 0x07, 0xf8, 0x87, 0x0f, }; unsigned int const C_badge_ethereum_colors[] = { - 0x00ffffff, - 0x00000000, + 0x00ffffff, + 0x00000000, }; unsigned char const C_badge_ethereum_bitmap[] = { - 0x1f, 0xfe, 0x01, 0x3e, 0x0c, 0x07, 0x83, 0xe1, 0x21, 0x78, 0x00, 0x3f, 0x80, 0x07, 0x10, 0x42, - 0x78, 0x18, 0x1e, 0x0e, 0xc3, 0x07, 0xf8, 0x87, 0x0f, + 0x1f, 0xfe, 0x01, 0x3e, 0x0c, 0x07, 0x83, 0xe1, 0x21, 0x78, 0x00, 0x3f, 0x80, + 0x07, 0x10, 0x42, 0x78, 0x18, 0x1e, 0x0e, 0xc3, 0x07, 0xf8, 0x87, 0x0f, }; unsigned int const C_badge_eye_colors[] = { - 0x00ffffff, - 0x00000000, + 0x00ffffff, + 0x00000000, }; unsigned char const C_badge_eye_bitmap[] = { - 0x1f, 0xfe, 0x01, 0x3e, 0x00, 0x07, 0x80, 0xe1, 0x21, 0xfe, 0xc1, 0xf3, 0xf0, 0x3c, 0xf8, 0x47, - 0x78, 0x18, 0x00, 0x0e, 0xc0, 0x07, 0xf8, 0x87, 0x0f, + 0x1f, 0xfe, 0x01, 0x3e, 0x00, 0x07, 0x80, 0xe1, 0x21, 0xfe, 0xc1, 0xf3, 0xf0, + 0x3c, 0xf8, 0x47, 0x78, 0x18, 0x00, 0x0e, 0xc0, 0x07, 0xf8, 0x87, 0x0f, }; unsigned int const C_badge_people_colors[] = { - 0x00ffffff, - 0x00000000, + 0x00ffffff, + 0x00000000, }; unsigned char const C_badge_people_bitmap[] = { - 0x1f, 0xfe, 0x01, 0x3e, 0x00, 0x07, 0x83, 0xe1, 0x21, 0x30, 0x00, 0x00, 0x80, 0x07, 0xf0, 0x43, - 0xfc, 0x18, 0x3f, 0x0e, 0xc0, 0x07, 0xf8, 0x87, 0x0f, + 0x1f, 0xfe, 0x01, 0x3e, 0x00, 0x07, 0x83, 0xe1, 0x21, 0x30, 0x00, 0x00, 0x80, + 0x07, 0xf0, 0x43, 0xfc, 0x18, 0x3f, 0x0e, 0xc0, 0x07, 0xf8, 0x87, 0x0f, }; unsigned int const C_badge_lock_colors[] = { - 0x00000000, - 0x00ffffff, + 0x00000000, + 0x00ffffff, }; unsigned char const C_badge_lock_bitmap[] = { - 0xe0, 0x01, 0xfe, 0xc1, 0xe1, 0x38, 0x70, 0xce, 0xdc, 0x33, 0x7f, 0x80, 0x1f, 0xe0, 0x07, 0xb8, - 0x01, 0x66, 0x80, 0xf1, 0x3f, 0xf8, 0x07, 0x78, 0x00, + 0xe0, 0x01, 0xfe, 0xc1, 0xe1, 0x38, 0x70, 0xce, 0xdc, 0x33, 0x7f, 0x80, 0x1f, + 0xe0, 0x07, 0xb8, 0x01, 0x66, 0x80, 0xf1, 0x3f, 0xf8, 0x07, 0x78, 0x00, }; -#define GLYPH_icon_blue_cable_WIDTH 65 +#define GLYPH_icon_blue_cable_WIDTH 65 #define GLYPH_icon_blue_cable_HEIGHT 62 -#define GLYPH_icon_blue_cable_BPP 2 +#define GLYPH_icon_blue_cable_BPP 2 unsigned int const C_icon_blue_cable_colors[] = { - 0x00d9d9d9, - 0x00cecece, - 0x00cccccc, - 0x00f9f9f9, + 0x00d9d9d9, + 0x00cecece, + 0x00cccccc, + 0x00f9f9f9, }; unsigned char const C_icon_blue_cable_bitmap[] = { - 0x4f, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xc6, 0xff, 0xff, 0xff, 0xff, 0xff, - 0x9f, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xfd, 0xff, 0xff, 0xff, 0xff, - 0x8f, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xca, 0xff, 0xff, 0xff, 0xff, - 0x7f, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0x6a, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xfe, 0xff, 0xff, 0xff, - 0xff, 0xab, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xfa, 0xff, 0xff, 0xff, - 0xff, 0xaf, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xea, 0xff, 0xff, 0xff, - 0xff, 0xbf, 0xaa, 0xfe, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xaf, 0xaa, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xaa, 0xfa, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xbf, 0xaa, 0xfe, 0xff, 0xff, - 0xff, 0xff, 0xab, 0xea, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xaa, 0xfa, 0xff, 0xff, - 0xff, 0xff, 0xaf, 0xaa, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xab, 0xea, 0xff, 0xff, - 0xff, 0xff, 0xbf, 0xaa, 0xfe, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xaf, 0xaa, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xaa, 0xfa, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xbf, 0xaa, 0xfe, 0xff, - 0xff, 0xff, 0xff, 0xab, 0xea, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xaa, 0xfa, 0xff, - 0xff, 0xff, 0xff, 0xaf, 0xaa, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xab, 0xea, 0xff, - 0xff, 0xff, 0xff, 0xbf, 0xaa, 0xfe, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xaf, 0xaa, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xaa, 0xfa, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xbf, 0xaa, 0xfe, - 0xff, 0xff, 0xff, 0xff, 0xab, 0xea, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xaa, 0xfa, - 0xff, 0xff, 0xff, 0xff, 0xaf, 0xaa, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xab, 0xea, - 0xff, 0xff, 0xbf, 0xaa, 0xbe, 0xaa, 0xfe, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xaf, 0xaa, - 0xff, 0xff, 0xff, 0xaa, 0xfa, 0xaa, 0xfa, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xbf, 0xaa, - 0xfe, 0xff, 0xff, 0xab, 0xea, 0xab, 0xea, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xaa, - 0xfa, 0xff, 0xff, 0xaf, 0xaa, 0xaf, 0xaa, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xab, - 0xea, 0xff, 0xff, 0xff, 0xff, 0xbf, 0xaa, 0xfe, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xaf, - 0xaa, 0xff, 0xff, 0x8f, 0xaa, 0x2a, 0xaa, 0xfa, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xbf, - 0xaa, 0xfe, 0xff, 0xbf, 0xaa, 0xaa, 0xaa, 0xea, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xaa, 0xfa, 0xff, 0xff, 0xaa, 0xaa, 0xaa, 0xaa, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xab, 0xea, 0xff, 0xff, 0xab, 0xaa, 0xaa, 0xaa, 0xfe, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xaf, 0xaa, 0xff, 0xff, 0xaf, 0xaa, 0xaa, 0xaa, 0xfa, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xbf, 0xaa, 0xfe, 0xff, 0xbf, 0xaa, 0xaa, 0xaa, 0xea, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xaa, 0xfa, 0xff, 0xff, 0xaa, 0xaa, 0xaa, 0xaa, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xab, 0xea, 0xff, 0xff, 0xab, 0xaa, 0xaa, 0xaa, 0xfe, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xaf, 0xaa, 0xff, 0xff, 0xaf, 0xaa, 0xaa, 0xaa, 0xfa, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xbf, 0xaa, 0xfe, 0xff, 0xbf, 0xaa, 0xaa, 0xaa, 0xea, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xaa, 0xfa, 0xff, 0xff, 0xaa, 0xaa, 0xaa, 0xaa, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xab, 0xea, 0xff, 0xff, 0xab, 0xaa, 0xaa, 0xaa, 0xfe, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xaf, 0xaa, 0xff, 0xff, 0xaf, 0xaa, 0xaa, 0xaa, 0xfa, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xbf, 0xaa, 0xfe, 0xff, 0xbf, 0xaa, 0xaa, 0xaa, 0xea, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xaa, 0xfa, 0xff, 0xff, 0xaa, 0xaa, 0xaa, 0xaa, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xab, 0xea, 0xff, 0xff, 0xab, 0xaa, 0xaa, 0xaa, 0xfe, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xaf, 0xaa, 0xff, 0xff, 0xaf, 0xaa, 0xaa, 0xaa, 0xfa, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xbf, 0xaa, 0xfe, 0xff, 0x3f, 0xaa, 0xaa, 0xa8, 0xea, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xaa, 0xfa, 0xff, 0xff, 0xff, 0xff, 0xaf, 0xaa, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xab, 0xea, 0xff, 0xff, 0xff, 0xaa, 0xbf, 0xaa, 0xfe, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xaf, 0xaa, 0xff, 0xff, 0xff, 0xab, 0xfe, 0xaa, 0xfa, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xbf, 0xaa, 0xfe, 0xff, 0xff, 0xaf, 0xfa, 0xab, 0xea, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xaa, 0xfa, 0xff, 0xff, 0xbf, 0xea, 0xaf, 0xaa, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xab, 0xea, 0xff, 0xff, 0xff, 0xaa, 0xbf, 0xaa, 0xfe, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xaf, 0xaa, 0xff, 0xff, 0xff, 0xab, 0xfe, 0xaa, 0xfa, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xbf, 0xaa, 0xfe, 0xff, 0xff, 0xaf, 0xfa, 0xab, 0xea, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xaa, 0xfa, 0xff, 0xff, 0xbf, 0xea, 0xaf, 0xaa, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xab, 0xea, 0xff, 0xff, 0xff, 0xff, 0xbf, 0xaa, 0xfe, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xaf, 0xaa, 0xff, 0xff, 0xff, 0xaf, 0xff, 0xaa, 0xfa, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xbf, 0xaa, 0xfe, 0xff, 0xff, 0xbf, 0xfe, 0xab, 0xea, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xaa, 0xfa, 0xff, 0xff, 0xff, 0xfa, 0xaf, 0xaa, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xab, 0xea, 0xff, 0xff, 0xff, 0xeb, 0xbf, 0xaa, 0xaa, - 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xff, 0xff, 0xff, 0xaf, 0xff, 0xaa, 0xaa, - 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xfe, 0xff, 0xff, 0xbf, 0xfe, 0xab, 0xaa, - 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xfa, 0xff, 0xff, 0xff, 0xfa, 0x9f, 0xaa, - 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xda, 0xff, 0xff, 0xff, 0xeb, 0x3f, 0xaa, - 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0x2a, 0xff, 0xff, 0xff, 0xaf, 0xff, 0xa7, - 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0x6a, 0xff, 0xff, 0xff, 0xbf, 0xfe, 0x3f, - 0xa9, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0x1a, 0xff, 0xff, 0xff, 0xff, 0xfa, 0x0f, - }; - -#define GLYPH_text_welcome_WIDTH 113 + 0x4f, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xc6, 0xff, 0xff, 0xff, 0xff, 0xff, + 0x9f, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xfd, 0xff, 0xff, 0xff, 0xff, + 0x8f, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xca, 0xff, 0xff, 0xff, 0xff, + 0x7f, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0x6a, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xfe, 0xff, 0xff, 0xff, + 0xff, 0xab, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xfa, 0xff, 0xff, 0xff, + 0xff, 0xaf, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xea, 0xff, 0xff, 0xff, + 0xff, 0xbf, 0xaa, 0xfe, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xaf, 0xaa, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xaa, 0xfa, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xbf, 0xaa, 0xfe, 0xff, 0xff, + 0xff, 0xff, 0xab, 0xea, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xaa, 0xfa, 0xff, 0xff, + 0xff, 0xff, 0xaf, 0xaa, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xab, 0xea, 0xff, 0xff, + 0xff, 0xff, 0xbf, 0xaa, 0xfe, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xaf, 0xaa, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xaa, 0xfa, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xbf, 0xaa, 0xfe, 0xff, + 0xff, 0xff, 0xff, 0xab, 0xea, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xaa, 0xfa, 0xff, + 0xff, 0xff, 0xff, 0xaf, 0xaa, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xab, 0xea, 0xff, + 0xff, 0xff, 0xff, 0xbf, 0xaa, 0xfe, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xaf, 0xaa, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xaa, 0xfa, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xbf, 0xaa, 0xfe, + 0xff, 0xff, 0xff, 0xff, 0xab, 0xea, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xaa, 0xfa, + 0xff, 0xff, 0xff, 0xff, 0xaf, 0xaa, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xab, 0xea, + 0xff, 0xff, 0xbf, 0xaa, 0xbe, 0xaa, 0xfe, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xaf, 0xaa, + 0xff, 0xff, 0xff, 0xaa, 0xfa, 0xaa, 0xfa, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xbf, 0xaa, + 0xfe, 0xff, 0xff, 0xab, 0xea, 0xab, 0xea, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xaa, + 0xfa, 0xff, 0xff, 0xaf, 0xaa, 0xaf, 0xaa, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xab, + 0xea, 0xff, 0xff, 0xff, 0xff, 0xbf, 0xaa, 0xfe, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xaf, + 0xaa, 0xff, 0xff, 0x8f, 0xaa, 0x2a, 0xaa, 0xfa, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xbf, + 0xaa, 0xfe, 0xff, 0xbf, 0xaa, 0xaa, 0xaa, 0xea, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xaa, 0xfa, 0xff, 0xff, 0xaa, 0xaa, 0xaa, 0xaa, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xab, 0xea, 0xff, 0xff, 0xab, 0xaa, 0xaa, 0xaa, 0xfe, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xaf, 0xaa, 0xff, 0xff, 0xaf, 0xaa, 0xaa, 0xaa, 0xfa, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xbf, 0xaa, 0xfe, 0xff, 0xbf, 0xaa, 0xaa, 0xaa, 0xea, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xaa, 0xfa, 0xff, 0xff, 0xaa, 0xaa, 0xaa, 0xaa, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xab, 0xea, 0xff, 0xff, 0xab, 0xaa, 0xaa, 0xaa, 0xfe, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xaf, 0xaa, 0xff, 0xff, 0xaf, 0xaa, 0xaa, 0xaa, 0xfa, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xbf, 0xaa, 0xfe, 0xff, 0xbf, 0xaa, 0xaa, 0xaa, 0xea, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xaa, 0xfa, 0xff, 0xff, 0xaa, 0xaa, 0xaa, 0xaa, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xab, 0xea, 0xff, 0xff, 0xab, 0xaa, 0xaa, 0xaa, 0xfe, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xaf, 0xaa, 0xff, 0xff, 0xaf, 0xaa, 0xaa, 0xaa, 0xfa, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xbf, 0xaa, 0xfe, 0xff, 0xbf, 0xaa, 0xaa, 0xaa, 0xea, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xaa, 0xfa, 0xff, 0xff, 0xaa, 0xaa, 0xaa, 0xaa, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xab, 0xea, 0xff, 0xff, 0xab, 0xaa, 0xaa, 0xaa, 0xfe, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xaf, 0xaa, 0xff, 0xff, 0xaf, 0xaa, 0xaa, 0xaa, 0xfa, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xbf, 0xaa, 0xfe, 0xff, 0x3f, 0xaa, 0xaa, 0xa8, 0xea, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xaa, 0xfa, 0xff, 0xff, 0xff, 0xff, 0xaf, 0xaa, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xab, 0xea, 0xff, 0xff, 0xff, 0xaa, 0xbf, 0xaa, 0xfe, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xaf, 0xaa, 0xff, 0xff, 0xff, 0xab, 0xfe, 0xaa, 0xfa, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xbf, 0xaa, 0xfe, 0xff, 0xff, 0xaf, 0xfa, 0xab, 0xea, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xaa, 0xfa, 0xff, 0xff, 0xbf, 0xea, 0xaf, 0xaa, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xab, 0xea, 0xff, 0xff, 0xff, 0xaa, 0xbf, 0xaa, 0xfe, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xaf, 0xaa, 0xff, 0xff, 0xff, 0xab, 0xfe, 0xaa, 0xfa, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xbf, 0xaa, 0xfe, 0xff, 0xff, 0xaf, 0xfa, 0xab, 0xea, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xaa, 0xfa, 0xff, 0xff, 0xbf, 0xea, 0xaf, 0xaa, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xab, 0xea, 0xff, 0xff, 0xff, 0xff, 0xbf, 0xaa, 0xfe, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xaf, 0xaa, 0xff, 0xff, 0xff, 0xaf, 0xff, 0xaa, 0xfa, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xbf, 0xaa, 0xfe, 0xff, 0xff, 0xbf, 0xfe, 0xab, 0xea, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xaa, 0xfa, 0xff, 0xff, 0xff, 0xfa, 0xaf, 0xaa, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xab, 0xea, 0xff, 0xff, 0xff, 0xeb, 0xbf, 0xaa, 0xaa, + 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xff, 0xff, 0xff, 0xaf, 0xff, 0xaa, 0xaa, + 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xfe, 0xff, 0xff, 0xbf, 0xfe, 0xab, 0xaa, + 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xfa, 0xff, 0xff, 0xff, 0xfa, 0x9f, 0xaa, + 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xda, 0xff, 0xff, 0xff, 0xeb, 0x3f, 0xaa, + 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0x2a, 0xff, 0xff, 0xff, 0xaf, 0xff, 0xa7, + 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0x6a, 0xff, 0xff, 0xff, 0xbf, 0xfe, 0x3f, + 0xa9, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0x1a, 0xff, 0xff, 0xff, 0xff, 0xfa, 0x0f, +}; + +#define GLYPH_text_welcome_WIDTH 113 #define GLYPH_text_welcome_HEIGHT 24 -#define GLYPH_text_welcome_BPP 4 +#define GLYPH_text_welcome_BPP 4 unsigned int const C_text_welcome_colors[] = { - 0x00c0c0c0, - 0x00555555, - 0x00eeeeee, - 0x00e3e3e3, - 0x00d8d8d8, - 0x00252525, - 0x00797979, - 0x00404040, - 0x00b3b3b3, - 0x00898989, - 0x00686868, - 0x00a6a6a6, - 0x00fafafa, - 0x00cccccc, - 0x00000000, - 0x00f9f9f9, + 0x00c0c0c0, + 0x00555555, + 0x00eeeeee, + 0x00e3e3e3, + 0x00d8d8d8, + 0x00252525, + 0x00797979, + 0x00404040, + 0x00b3b3b3, + 0x00898989, + 0x00686868, + 0x00a6a6a6, + 0x00fafafa, + 0x00cccccc, + 0x00000000, + 0x00f9f9f9, }; unsigned char const C_text_welcome_bitmap[] = { - 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, - 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0x0b, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, - 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, - 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0x3c, 0x4b, 0xff, 0xff, 0xff, 0xff, 0x0f, 0x3b, - 0xff, 0xff, 0xff, 0xff, 0xdf, 0xfb, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xaf, 0xfb, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xef, 0xfb, 0xff, 0xff, 0xff, 0xff, 0xe1, 0xfb, 0xff, 0xff, 0xff, 0xff, 0xaa, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xba, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x76, 0xff, 0xff, 0xff, 0xff, 0xe2, - 0x61, 0xff, 0xff, 0xff, 0xff, 0xe2, 0xfb, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xaf, 0xfb, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xbf, 0x3e, 0xff, 0xff, 0xff, 0x8f, 0x8e, 0xfe, 0xff, 0xff, 0xff, 0x0f, 0x4e, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xba, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xe3, 0xf8, 0xff, 0xff, 0xff, - 0xa9, 0xe3, 0xf0, 0xff, 0xff, 0xff, 0x7b, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xaf, - 0xfb, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0x67, 0xff, 0xff, 0xff, 0x5f, 0xfb, 0xb1, 0xff, 0xff, 0xff, 0x7f, 0xf9, - 0xff, 0xff, 0xff, 0xd4, 0xfd, 0xff, 0xff, 0xff, 0xba, 0xff, 0xff, 0xff, 0xff, 0xd4, 0x3d, 0xff, - 0xff, 0xff, 0xff, 0xd4, 0x2d, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xd3, 0x2d, 0xff, 0xff, 0xff, - 0xd3, 0x2d, 0xff, 0xff, 0xff, 0xff, 0xff, 0xd2, 0x3d, 0xff, 0xff, 0xff, 0x9f, 0xf5, 0xff, 0xff, - 0x4f, 0x4e, 0xbf, 0xf7, 0xff, 0xff, 0x3f, 0x8e, 0xff, 0xff, 0xb2, 0xe5, 0xee, 0x9e, 0xf2, 0xff, - 0xaf, 0xfb, 0xff, 0xff, 0x93, 0xee, 0xee, 0x5e, 0xfb, 0xff, 0xb2, 0xe5, 0xee, 0xae, 0xfd, 0xff, - 0xff, 0xed, 0x4f, 0xea, 0xee, 0xae, 0xf4, 0x0f, 0xe7, 0xee, 0xae, 0xf3, 0xff, 0xff, 0xdf, 0xea, - 0xee, 0x7e, 0xf0, 0xff, 0xff, 0xe0, 0xf4, 0xff, 0xff, 0x5b, 0xff, 0xed, 0xf3, 0xff, 0xff, 0xe8, - 0xf2, 0xff, 0x12, 0xb5, 0xf3, 0x82, 0x15, 0xf2, 0xff, 0xba, 0xff, 0xff, 0x58, 0x0a, 0xf2, 0xdf, - 0x0b, 0xff, 0x12, 0x85, 0xf3, 0x0f, 0xe6, 0xf8, 0xff, 0xdf, 0xde, 0xb7, 0xf3, 0x0f, 0x51, 0x83, - 0xb5, 0xf3, 0x0f, 0x51, 0xf2, 0xff, 0x8f, 0xae, 0xf0, 0x4f, 0xe6, 0xf8, 0xff, 0x2f, 0xbe, 0xff, - 0xff, 0xaf, 0xf9, 0xff, 0xb5, 0xff, 0xff, 0x9f, 0xf1, 0xff, 0xaf, 0x45, 0xff, 0xff, 0x4f, 0x65, - 0xff, 0xaf, 0xfb, 0xff, 0xe4, 0xf9, 0xff, 0xff, 0xff, 0xff, 0x1f, 0x27, 0xff, 0xff, 0xff, 0xeb, - 0xf0, 0xff, 0xed, 0xde, 0xff, 0xff, 0x2f, 0x15, 0x4e, 0xff, 0xff, 0x2f, 0xb5, 0xff, 0xdf, 0x9e, - 0xff, 0xff, 0xff, 0xe9, 0xf4, 0xff, 0x1f, 0xfa, 0xff, 0x2f, 0x8e, 0xff, 0x6f, 0xf6, 0xff, 0xff, - 0xb5, 0xff, 0xdf, 0x0e, 0xff, 0xff, 0xff, 0x8f, 0x4e, 0xff, 0xba, 0xff, 0xaf, 0xfa, 0xff, 0xff, - 0xff, 0xff, 0x8f, 0xde, 0xff, 0xff, 0xff, 0xff, 0x7a, 0xff, 0xdf, 0x6e, 0xff, 0xff, 0xff, 0xbf, - 0x9e, 0xff, 0xff, 0xff, 0x9f, 0xf1, 0xff, 0x1a, 0xff, 0xff, 0xff, 0xff, 0x67, 0xff, 0xff, 0xeb, - 0xff, 0xff, 0xe0, 0xf3, 0xff, 0xe8, 0xff, 0xff, 0xe4, 0xfd, 0xff, 0x76, 0xff, 0xff, 0xff, 0xff, - 0xe2, 0xfb, 0xaf, 0xfb, 0x4f, 0x0e, 0xff, 0xff, 0xff, 0xff, 0xff, 0x11, 0xff, 0xff, 0xff, 0xff, - 0x0f, 0x0e, 0xff, 0xed, 0xf8, 0xff, 0xff, 0xff, 0xeb, 0xfd, 0xff, 0xff, 0xff, 0xeb, 0xff, 0xe4, - 0xf8, 0xff, 0xff, 0xff, 0xbf, 0xfe, 0xff, 0xdf, 0x0e, 0xff, 0x9f, 0xf1, 0xff, 0x3f, 0x0e, 0xff, - 0xbf, 0xf5, 0xff, 0xef, 0xfb, 0xff, 0xff, 0xff, 0xff, 0x67, 0xff, 0xba, 0xff, 0xeb, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xef, 0xfb, 0xff, 0xff, 0xff, 0xff, 0xef, 0xfb, 0xdf, 0xde, 0xff, 0xff, 0xff, - 0xbf, 0x3e, 0xff, 0xff, 0xff, 0xbf, 0xfe, 0xbf, 0x2e, 0xff, 0xff, 0xff, 0xff, 0xe8, 0xf4, 0xff, - 0x5f, 0xfb, 0xff, 0xb7, 0xff, 0xff, 0x1f, 0xfb, 0xff, 0x66, 0xff, 0x4f, 0xbe, 0xff, 0xff, 0xff, - 0xff, 0xaf, 0xfa, 0xaf, 0xfb, 0x6f, 0xf1, 0xff, 0xff, 0xff, 0xff, 0xdf, 0x0e, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xa1, 0xff, 0xed, 0xf4, 0xff, 0xff, 0xff, 0xeb, 0xff, 0xff, 0xff, 0xff, 0xeb, 0xff, - 0x56, 0xff, 0xff, 0xff, 0xff, 0xdf, 0xde, 0xff, 0xff, 0x16, 0xff, 0xe4, 0xfd, 0xff, 0xff, 0x7b, - 0xff, 0xef, 0xfb, 0xff, 0xed, 0xee, 0xee, 0xee, 0xee, 0xee, 0xae, 0xff, 0xba, 0xff, 0xaa, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xed, 0xfd, 0xff, 0xff, 0xff, 0xff, 0xaf, 0xfa, 0xdf, 0xfe, 0xff, 0xff, - 0xff, 0xbf, 0xfe, 0xff, 0xff, 0xff, 0xbf, 0xfe, 0xaf, 0xee, 0xee, 0xee, 0xee, 0xee, 0xee, 0xfd, - 0xff, 0xbf, 0x3e, 0xbf, 0xfe, 0xff, 0xff, 0xdf, 0x3e, 0xdf, 0x3e, 0xff, 0xdf, 0xbe, 0xdd, 0xdd, - 0xdd, 0xdd, 0xdd, 0xf4, 0xaf, 0xfb, 0xaf, 0xfa, 0xff, 0xff, 0xff, 0xff, 0xdf, 0xde, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xaa, 0xff, 0xed, 0xff, 0xff, 0xff, 0xff, 0xeb, 0xff, 0xff, 0xff, 0xff, 0xeb, - 0xff, 0x1a, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0x2d, 0xff, 0xff, 0xe3, 0xf8, 0x66, 0xff, 0xff, 0xff, - 0xef, 0xfb, 0x7b, 0xff, 0xff, 0xed, 0xf0, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xba, 0xff, 0x1a, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xed, 0xf0, 0xff, 0xff, 0xff, 0xff, 0x1f, 0xfa, 0xdf, 0xfe, 0xff, - 0xff, 0xff, 0xbf, 0xfe, 0xff, 0xff, 0xff, 0xbf, 0xfe, 0xaf, 0xf1, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0x97, 0xef, 0xfb, 0xff, 0xff, 0xff, 0x66, 0x1f, 0xf9, 0xff, 0xff, 0xbe, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xaf, 0xfb, 0xbf, 0xfe, 0xff, 0xff, 0xff, 0xff, 0xff, 0xbe, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xbe, 0xff, 0xed, 0xff, 0xff, 0xff, 0xff, 0xeb, 0xff, 0xff, 0xff, 0xff, - 0xeb, 0xff, 0xeb, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x9f, 0xd7, 0x3e, 0xff, 0xff, - 0xff, 0xbf, 0x2e, 0x0e, 0xff, 0xff, 0x1f, 0xf1, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xba, 0xff, - 0xe0, 0xf0, 0xff, 0xff, 0xff, 0xff, 0x6f, 0xf1, 0xff, 0xff, 0xff, 0xff, 0xe0, 0xf0, 0xdf, 0xfe, - 0xff, 0xff, 0xff, 0xbf, 0xfe, 0xff, 0xff, 0xff, 0xbf, 0xfe, 0x0f, 0x0e, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xe0, 0x7b, 0xff, 0xff, 0xff, 0xff, 0xe3, 0xeb, 0xf2, 0xff, 0xff, 0xe8, - 0xfd, 0xff, 0xff, 0xff, 0xff, 0xff, 0xaf, 0xfb, 0xff, 0x17, 0xff, 0xff, 0xff, 0xff, 0xff, 0xe8, - 0xfd, 0xff, 0xff, 0xff, 0xaf, 0xf7, 0xff, 0xed, 0xff, 0xff, 0xff, 0xff, 0xeb, 0xff, 0xff, 0xff, - 0xff, 0xeb, 0xff, 0x7f, 0xfa, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x2f, 0x5e, 0xfb, 0xff, - 0xff, 0xff, 0xff, 0xe7, 0xf1, 0xff, 0xff, 0xff, 0x51, 0xf4, 0xff, 0xff, 0xff, 0xff, 0xff, 0xba, - 0xff, 0x0f, 0x9e, 0xff, 0xff, 0xff, 0xff, 0xff, 0x5a, 0xf3, 0xff, 0xff, 0xbf, 0x0e, 0xff, 0xdf, - 0xfe, 0xff, 0xff, 0xff, 0xbf, 0xfe, 0xff, 0xff, 0xff, 0xbf, 0xfe, 0xff, 0xe0, 0xf9, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0x1f, 0x0e, 0xff, 0xff, 0xff, 0xff, 0xbf, 0xbe, 0xff, 0xff, 0xff, - 0x2f, 0x51, 0x4b, 0xff, 0xdf, 0x1b, 0xfd, 0xaf, 0xfb, 0xff, 0x8f, 0xae, 0x20, 0xff, 0xb4, 0xf0, - 0x2f, 0x51, 0x3b, 0xff, 0x60, 0x8e, 0xff, 0xff, 0xed, 0xff, 0xff, 0xff, 0xff, 0xeb, 0xff, 0xff, - 0xff, 0xff, 0xeb, 0xff, 0xff, 0xe8, 0x0a, 0xf2, 0x3f, 0x90, 0xf6, 0xff, 0xff, 0xff, 0xeb, 0xf2, - 0xff, 0xff, 0xff, 0xff, 0xe0, 0xf4, 0xff, 0xff, 0xff, 0x2f, 0x7b, 0xee, 0xee, 0x7e, 0x2b, 0xff, - 0xba, 0xff, 0xff, 0xdf, 0xe6, 0xee, 0xee, 0x07, 0xff, 0x2f, 0x5b, 0xee, 0xee, 0xda, 0xff, 0xff, - 0xdf, 0xfe, 0xff, 0xff, 0xff, 0xbf, 0xfe, 0xff, 0xff, 0xff, 0xbf, 0xfe, 0xff, 0xff, 0x6d, 0xee, - 0xee, 0xee, 0x06, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0x3f, 0xdd, 0x2d, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xdf, 0xdd, 0xf3, - 0xff, 0xff, 0xff, 0x4f, 0xdd, 0xf2, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xdd, 0x4d, 0xff, 0xff, }; - -#define GLYPH_logo_ledger_boot_WIDTH 50 + 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, + 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0x0b, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, + 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, + 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0x3c, 0x4b, 0xff, 0xff, 0xff, 0xff, 0x0f, 0x3b, + 0xff, 0xff, 0xff, 0xff, 0xdf, 0xfb, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xaf, 0xfb, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xef, 0xfb, 0xff, 0xff, 0xff, 0xff, 0xe1, 0xfb, 0xff, 0xff, 0xff, 0xff, 0xaa, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xba, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x76, 0xff, 0xff, 0xff, 0xff, 0xe2, + 0x61, 0xff, 0xff, 0xff, 0xff, 0xe2, 0xfb, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xaf, 0xfb, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xbf, 0x3e, 0xff, 0xff, 0xff, 0x8f, 0x8e, 0xfe, 0xff, 0xff, 0xff, 0x0f, 0x4e, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xba, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xe3, 0xf8, 0xff, 0xff, 0xff, + 0xa9, 0xe3, 0xf0, 0xff, 0xff, 0xff, 0x7b, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xaf, + 0xfb, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0x67, 0xff, 0xff, 0xff, 0x5f, 0xfb, 0xb1, 0xff, 0xff, 0xff, 0x7f, 0xf9, + 0xff, 0xff, 0xff, 0xd4, 0xfd, 0xff, 0xff, 0xff, 0xba, 0xff, 0xff, 0xff, 0xff, 0xd4, 0x3d, 0xff, + 0xff, 0xff, 0xff, 0xd4, 0x2d, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xd3, 0x2d, 0xff, 0xff, 0xff, + 0xd3, 0x2d, 0xff, 0xff, 0xff, 0xff, 0xff, 0xd2, 0x3d, 0xff, 0xff, 0xff, 0x9f, 0xf5, 0xff, 0xff, + 0x4f, 0x4e, 0xbf, 0xf7, 0xff, 0xff, 0x3f, 0x8e, 0xff, 0xff, 0xb2, 0xe5, 0xee, 0x9e, 0xf2, 0xff, + 0xaf, 0xfb, 0xff, 0xff, 0x93, 0xee, 0xee, 0x5e, 0xfb, 0xff, 0xb2, 0xe5, 0xee, 0xae, 0xfd, 0xff, + 0xff, 0xed, 0x4f, 0xea, 0xee, 0xae, 0xf4, 0x0f, 0xe7, 0xee, 0xae, 0xf3, 0xff, 0xff, 0xdf, 0xea, + 0xee, 0x7e, 0xf0, 0xff, 0xff, 0xe0, 0xf4, 0xff, 0xff, 0x5b, 0xff, 0xed, 0xf3, 0xff, 0xff, 0xe8, + 0xf2, 0xff, 0x12, 0xb5, 0xf3, 0x82, 0x15, 0xf2, 0xff, 0xba, 0xff, 0xff, 0x58, 0x0a, 0xf2, 0xdf, + 0x0b, 0xff, 0x12, 0x85, 0xf3, 0x0f, 0xe6, 0xf8, 0xff, 0xdf, 0xde, 0xb7, 0xf3, 0x0f, 0x51, 0x83, + 0xb5, 0xf3, 0x0f, 0x51, 0xf2, 0xff, 0x8f, 0xae, 0xf0, 0x4f, 0xe6, 0xf8, 0xff, 0x2f, 0xbe, 0xff, + 0xff, 0xaf, 0xf9, 0xff, 0xb5, 0xff, 0xff, 0x9f, 0xf1, 0xff, 0xaf, 0x45, 0xff, 0xff, 0x4f, 0x65, + 0xff, 0xaf, 0xfb, 0xff, 0xe4, 0xf9, 0xff, 0xff, 0xff, 0xff, 0x1f, 0x27, 0xff, 0xff, 0xff, 0xeb, + 0xf0, 0xff, 0xed, 0xde, 0xff, 0xff, 0x2f, 0x15, 0x4e, 0xff, 0xff, 0x2f, 0xb5, 0xff, 0xdf, 0x9e, + 0xff, 0xff, 0xff, 0xe9, 0xf4, 0xff, 0x1f, 0xfa, 0xff, 0x2f, 0x8e, 0xff, 0x6f, 0xf6, 0xff, 0xff, + 0xb5, 0xff, 0xdf, 0x0e, 0xff, 0xff, 0xff, 0x8f, 0x4e, 0xff, 0xba, 0xff, 0xaf, 0xfa, 0xff, 0xff, + 0xff, 0xff, 0x8f, 0xde, 0xff, 0xff, 0xff, 0xff, 0x7a, 0xff, 0xdf, 0x6e, 0xff, 0xff, 0xff, 0xbf, + 0x9e, 0xff, 0xff, 0xff, 0x9f, 0xf1, 0xff, 0x1a, 0xff, 0xff, 0xff, 0xff, 0x67, 0xff, 0xff, 0xeb, + 0xff, 0xff, 0xe0, 0xf3, 0xff, 0xe8, 0xff, 0xff, 0xe4, 0xfd, 0xff, 0x76, 0xff, 0xff, 0xff, 0xff, + 0xe2, 0xfb, 0xaf, 0xfb, 0x4f, 0x0e, 0xff, 0xff, 0xff, 0xff, 0xff, 0x11, 0xff, 0xff, 0xff, 0xff, + 0x0f, 0x0e, 0xff, 0xed, 0xf8, 0xff, 0xff, 0xff, 0xeb, 0xfd, 0xff, 0xff, 0xff, 0xeb, 0xff, 0xe4, + 0xf8, 0xff, 0xff, 0xff, 0xbf, 0xfe, 0xff, 0xdf, 0x0e, 0xff, 0x9f, 0xf1, 0xff, 0x3f, 0x0e, 0xff, + 0xbf, 0xf5, 0xff, 0xef, 0xfb, 0xff, 0xff, 0xff, 0xff, 0x67, 0xff, 0xba, 0xff, 0xeb, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xef, 0xfb, 0xff, 0xff, 0xff, 0xff, 0xef, 0xfb, 0xdf, 0xde, 0xff, 0xff, 0xff, + 0xbf, 0x3e, 0xff, 0xff, 0xff, 0xbf, 0xfe, 0xbf, 0x2e, 0xff, 0xff, 0xff, 0xff, 0xe8, 0xf4, 0xff, + 0x5f, 0xfb, 0xff, 0xb7, 0xff, 0xff, 0x1f, 0xfb, 0xff, 0x66, 0xff, 0x4f, 0xbe, 0xff, 0xff, 0xff, + 0xff, 0xaf, 0xfa, 0xaf, 0xfb, 0x6f, 0xf1, 0xff, 0xff, 0xff, 0xff, 0xdf, 0x0e, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xa1, 0xff, 0xed, 0xf4, 0xff, 0xff, 0xff, 0xeb, 0xff, 0xff, 0xff, 0xff, 0xeb, 0xff, + 0x56, 0xff, 0xff, 0xff, 0xff, 0xdf, 0xde, 0xff, 0xff, 0x16, 0xff, 0xe4, 0xfd, 0xff, 0xff, 0x7b, + 0xff, 0xef, 0xfb, 0xff, 0xed, 0xee, 0xee, 0xee, 0xee, 0xee, 0xae, 0xff, 0xba, 0xff, 0xaa, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xed, 0xfd, 0xff, 0xff, 0xff, 0xff, 0xaf, 0xfa, 0xdf, 0xfe, 0xff, 0xff, + 0xff, 0xbf, 0xfe, 0xff, 0xff, 0xff, 0xbf, 0xfe, 0xaf, 0xee, 0xee, 0xee, 0xee, 0xee, 0xee, 0xfd, + 0xff, 0xbf, 0x3e, 0xbf, 0xfe, 0xff, 0xff, 0xdf, 0x3e, 0xdf, 0x3e, 0xff, 0xdf, 0xbe, 0xdd, 0xdd, + 0xdd, 0xdd, 0xdd, 0xf4, 0xaf, 0xfb, 0xaf, 0xfa, 0xff, 0xff, 0xff, 0xff, 0xdf, 0xde, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xaa, 0xff, 0xed, 0xff, 0xff, 0xff, 0xff, 0xeb, 0xff, 0xff, 0xff, 0xff, 0xeb, + 0xff, 0x1a, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0x2d, 0xff, 0xff, 0xe3, 0xf8, 0x66, 0xff, 0xff, 0xff, + 0xef, 0xfb, 0x7b, 0xff, 0xff, 0xed, 0xf0, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xba, 0xff, 0x1a, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xed, 0xf0, 0xff, 0xff, 0xff, 0xff, 0x1f, 0xfa, 0xdf, 0xfe, 0xff, + 0xff, 0xff, 0xbf, 0xfe, 0xff, 0xff, 0xff, 0xbf, 0xfe, 0xaf, 0xf1, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0x97, 0xef, 0xfb, 0xff, 0xff, 0xff, 0x66, 0x1f, 0xf9, 0xff, 0xff, 0xbe, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xaf, 0xfb, 0xbf, 0xfe, 0xff, 0xff, 0xff, 0xff, 0xff, 0xbe, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xbe, 0xff, 0xed, 0xff, 0xff, 0xff, 0xff, 0xeb, 0xff, 0xff, 0xff, 0xff, + 0xeb, 0xff, 0xeb, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x9f, 0xd7, 0x3e, 0xff, 0xff, + 0xff, 0xbf, 0x2e, 0x0e, 0xff, 0xff, 0x1f, 0xf1, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xba, 0xff, + 0xe0, 0xf0, 0xff, 0xff, 0xff, 0xff, 0x6f, 0xf1, 0xff, 0xff, 0xff, 0xff, 0xe0, 0xf0, 0xdf, 0xfe, + 0xff, 0xff, 0xff, 0xbf, 0xfe, 0xff, 0xff, 0xff, 0xbf, 0xfe, 0x0f, 0x0e, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xe0, 0x7b, 0xff, 0xff, 0xff, 0xff, 0xe3, 0xeb, 0xf2, 0xff, 0xff, 0xe8, + 0xfd, 0xff, 0xff, 0xff, 0xff, 0xff, 0xaf, 0xfb, 0xff, 0x17, 0xff, 0xff, 0xff, 0xff, 0xff, 0xe8, + 0xfd, 0xff, 0xff, 0xff, 0xaf, 0xf7, 0xff, 0xed, 0xff, 0xff, 0xff, 0xff, 0xeb, 0xff, 0xff, 0xff, + 0xff, 0xeb, 0xff, 0x7f, 0xfa, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x2f, 0x5e, 0xfb, 0xff, + 0xff, 0xff, 0xff, 0xe7, 0xf1, 0xff, 0xff, 0xff, 0x51, 0xf4, 0xff, 0xff, 0xff, 0xff, 0xff, 0xba, + 0xff, 0x0f, 0x9e, 0xff, 0xff, 0xff, 0xff, 0xff, 0x5a, 0xf3, 0xff, 0xff, 0xbf, 0x0e, 0xff, 0xdf, + 0xfe, 0xff, 0xff, 0xff, 0xbf, 0xfe, 0xff, 0xff, 0xff, 0xbf, 0xfe, 0xff, 0xe0, 0xf9, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0x1f, 0x0e, 0xff, 0xff, 0xff, 0xff, 0xbf, 0xbe, 0xff, 0xff, 0xff, + 0x2f, 0x51, 0x4b, 0xff, 0xdf, 0x1b, 0xfd, 0xaf, 0xfb, 0xff, 0x8f, 0xae, 0x20, 0xff, 0xb4, 0xf0, + 0x2f, 0x51, 0x3b, 0xff, 0x60, 0x8e, 0xff, 0xff, 0xed, 0xff, 0xff, 0xff, 0xff, 0xeb, 0xff, 0xff, + 0xff, 0xff, 0xeb, 0xff, 0xff, 0xe8, 0x0a, 0xf2, 0x3f, 0x90, 0xf6, 0xff, 0xff, 0xff, 0xeb, 0xf2, + 0xff, 0xff, 0xff, 0xff, 0xe0, 0xf4, 0xff, 0xff, 0xff, 0x2f, 0x7b, 0xee, 0xee, 0x7e, 0x2b, 0xff, + 0xba, 0xff, 0xff, 0xdf, 0xe6, 0xee, 0xee, 0x07, 0xff, 0x2f, 0x5b, 0xee, 0xee, 0xda, 0xff, 0xff, + 0xdf, 0xfe, 0xff, 0xff, 0xff, 0xbf, 0xfe, 0xff, 0xff, 0xff, 0xbf, 0xfe, 0xff, 0xff, 0x6d, 0xee, + 0xee, 0xee, 0x06, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0x3f, 0xdd, 0x2d, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xdf, 0xdd, 0xf3, + 0xff, 0xff, 0xff, 0x4f, 0xdd, 0xf2, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xdd, 0x4d, 0xff, 0xff, +}; + +#define GLYPH_logo_ledger_boot_WIDTH 50 #define GLYPH_logo_ledger_boot_HEIGHT 50 -#define GLYPH_logo_ledger_boot_BPP 4 +#define GLYPH_logo_ledger_boot_BPP 4 unsigned int const C_logo_ledger_boot_colors[] = { - 0x0083858e, - 0x00f2f2f3, - 0x00646772, - 0x004a4e5a, - 0x00565965, - 0x00393d4a, - 0x00525561, - 0x00888a92, - 0x008b8d95, - 0x00353946, - 0x00d8d9db, - 0x00d2d3d6, - 0x003f4250, - 0x00404451, - 0x00f9f9f9, - 0x00333745, + 0x0083858e, + 0x00f2f2f3, + 0x00646772, + 0x004a4e5a, + 0x00565965, + 0x00393d4a, + 0x00525561, + 0x00888a92, + 0x008b8d95, + 0x00353946, + 0x00d8d9db, + 0x00d2d3d6, + 0x003f4250, + 0x00404451, + 0x00f9f9f9, + 0x00333745, }; unsigned char const C_logo_ledger_boot_bitmap[] = { - 0xee, 0xee, 0x7a, 0x56, 0xff, 0x3f, 0xee, 0xee, 0xee, 0xce, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0x65, 0xa8, 0xee, 0xee, 0xee, 0x01, 0xf9, 0xff, 0xff, 0x3f, 0xee, - 0xee, 0xee, 0xce, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x9f, - 0x10, 0xee, 0x1e, 0xf2, 0xff, 0xff, 0xff, 0x3f, 0xee, 0xee, 0xee, 0xce, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x2f, 0xe1, 0x0e, 0xff, 0xff, 0xff, 0xff, - 0x3f, 0xee, 0xee, 0xee, 0xce, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xe0, 0x9b, 0xff, 0xff, 0xff, 0xff, 0x3f, 0xee, 0xee, 0xee, 0xce, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xa9, 0xf7, 0xff, 0xff, - 0xff, 0xff, 0x3f, 0xee, 0xee, 0xee, 0xce, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0x7f, 0xf6, 0xff, 0xff, 0xff, 0xff, 0x3f, 0xee, 0xee, 0xee, 0xce, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x4f, 0xf5, - 0xff, 0xff, 0xff, 0xff, 0x3f, 0xee, 0xee, 0xee, 0xce, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xcf, 0xff, 0xff, 0xff, 0xff, 0xff, 0x3f, 0xee, 0xee, - 0xee, 0xce, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x3f, 0xee, 0xee, 0xee, 0xce, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x3f, - 0xee, 0xee, 0xee, 0xce, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0x4d, 0xee, 0xee, 0xee, 0xce, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xee, 0xee, 0xee, 0xee, - 0xee, 0xee, 0xee, 0xee, 0xee, 0xce, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xee, 0xee, 0xee, 0xee, 0xee, 0xee, 0xee, 0xee, 0xee, 0xce, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xee, 0xee, - 0xee, 0xee, 0xee, 0xee, 0xee, 0xee, 0xee, 0xce, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xee, 0xee, 0xee, 0xee, 0xee, 0xee, 0xee, 0xee, 0xee, - 0xce, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xee, 0xee, 0xee, 0xee, 0xee, 0xee, 0xee, 0xee, 0xee, 0xce, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xee, 0xee, 0xee, 0xee, 0xee, 0xee, 0xee, - 0xee, 0xee, 0xce, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xee, 0xee, 0xee, 0xee, 0xee, 0xee, 0xee, 0xee, 0xee, 0xce, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, - 0x4d, 0xee, 0xee, 0xee, 0xce, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x3f, 0xee, 0xee, 0xee, 0xce, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0x3f, 0xee, 0xee, 0xee, 0xce, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x3f, 0xee, 0xee, 0xee, 0xce, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0x3f, 0xee, 0xee, 0xee, 0xce, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x3f, 0xee, 0xee, - 0xee, 0xce, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x3f, 0xee, 0xee, 0xee, 0xce, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x3f, - 0xee, 0xee, 0xee, 0xce, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x3f, 0xee, 0xee, 0xee, 0xce, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0x3f, 0xee, 0xee, 0xee, 0xce, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x3f, 0xee, 0xee, 0xee, 0xce, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xdd, 0xdd, - 0xdd, 0xdd, 0xdd, 0x4d, 0xee, 0xee, 0xee, 0x3e, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, - 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xee, 0xee, 0xee, 0xee, 0xee, 0xee, 0xee, 0xee, 0xee, - 0xee, 0xee, 0xee, 0xee, 0xee, 0xee, 0xee, 0xee, 0xee, 0xee, 0xee, 0xee, 0xee, 0xee, 0xee, 0xee, - 0xee, 0xee, 0xee, 0xee, 0xee, 0xee, 0xee, 0xee, 0xee, 0xee, 0xee, 0xee, 0xee, 0xee, 0xee, 0xee, - 0xee, 0xee, 0xee, 0xee, 0xee, 0xee, 0xee, 0xee, 0xee, 0xee, 0xee, 0xee, 0xee, 0xee, 0xee, 0xee, - 0xee, 0xee, 0xee, 0xee, 0xee, 0xee, 0xee, 0xee, 0xee, 0xee, 0xee, 0xee, 0xee, 0xee, 0xee, 0xee, - 0xee, 0xee, 0xee, 0xee, 0xee, 0xee, 0xee, 0xee, 0xee, 0xee, 0xee, 0xee, 0xee, 0xee, 0xee, 0xee, - 0xee, 0xee, 0xee, 0xee, 0xee, 0xee, 0xee, 0xee, 0xee, 0xee, 0xee, 0xee, 0xee, 0xee, 0xee, 0xee, - 0xee, 0xee, 0xee, 0xee, 0xee, 0xee, 0xee, 0xee, 0xee, 0xee, 0xee, 0xee, 0xee, 0xee, 0xee, 0xee, - 0xee, 0xee, 0xee, 0xee, 0xee, 0xee, 0xee, 0xee, 0xee, 0xee, 0xee, 0xee, 0xee, 0xee, 0xee, 0xee, - 0xee, 0xee, 0xee, 0xee, 0xee, 0xee, 0xee, 0xee, 0xee, 0xee, 0xee, 0xee, 0xee, 0xee, 0xee, 0xee, - 0xee, 0xee, 0xee, 0xee, 0xee, 0xee, 0xee, 0xee, 0xee, 0xee, 0xee, 0xee, 0xee, 0xee, 0xee, 0xee, - 0xee, 0xee, 0xee, 0xee, 0xee, 0xee, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0x4d, 0xee, 0xee, 0xee, 0x3e, - 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xe3, 0xee, 0xee, 0xee, 0xd4, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xff, - 0xff, 0xff, 0xff, 0xff, 0x3f, 0xee, 0xee, 0xee, 0xce, 0xff, 0xff, 0xff, 0xff, 0xff, 0xec, 0xee, - 0xee, 0xee, 0xf3, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x3f, 0xee, 0xee, - 0xee, 0xce, 0xff, 0xff, 0xff, 0xff, 0xff, 0xec, 0xee, 0xee, 0xee, 0xf3, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x3f, 0xee, 0xee, 0xee, 0xce, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xec, 0xee, 0xee, 0xee, 0xf3, 0xff, 0xff, 0xff, 0xff, 0xff, 0xf9, 0xff, 0xff, 0xff, 0xff, 0x3f, - 0xee, 0xee, 0xee, 0xce, 0xff, 0xff, 0xff, 0xff, 0xff, 0xec, 0xee, 0xee, 0xee, 0xf3, 0xff, 0xff, - 0xff, 0xff, 0x5f, 0xf6, 0xff, 0xff, 0xff, 0xff, 0x3f, 0xee, 0xee, 0xee, 0xce, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xec, 0xee, 0xee, 0xee, 0xf3, 0xff, 0xff, 0xff, 0xff, 0x6f, 0xf7, 0xff, 0xff, 0xff, - 0xff, 0x3f, 0xee, 0xee, 0xee, 0xce, 0xff, 0xff, 0xff, 0xff, 0xff, 0xec, 0xee, 0xee, 0xee, 0xf3, - 0xff, 0xff, 0xff, 0xff, 0x8f, 0x9b, 0xff, 0xff, 0xff, 0xff, 0x3f, 0xee, 0xee, 0xee, 0xce, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xec, 0xee, 0xee, 0xee, 0xf3, 0xff, 0xff, 0xff, 0xff, 0xa9, 0x0e, 0xff, - 0xff, 0xff, 0xff, 0x3f, 0xee, 0xee, 0xee, 0xce, 0xff, 0xff, 0xff, 0xff, 0xff, 0xec, 0xee, 0xee, - 0xee, 0xf3, 0xff, 0xff, 0xff, 0xff, 0xe0, 0x1e, 0xf2, 0xff, 0xff, 0xff, 0x3f, 0xee, 0xee, 0xee, - 0xce, 0xff, 0xff, 0xff, 0xff, 0xff, 0xec, 0xee, 0xee, 0xee, 0xf3, 0xff, 0xff, 0xff, 0x2f, 0xe1, - 0xee, 0x01, 0xf9, 0xff, 0xff, 0x3f, 0xee, 0xee, 0xee, 0xce, 0xff, 0xff, 0xff, 0xff, 0xff, 0xec, - 0xee, 0xee, 0xee, 0xf3, 0xff, 0xff, 0x9f, 0x17, 0xee, 0xee, 0xee, 0x8a, 0x56, 0xff, 0x3f, 0xee, - 0xee, 0xee, 0xce, 0xff, 0xff, 0xff, 0xff, 0xff, 0xec, 0xee, 0xee, 0xee, 0xf3, 0xff, 0x65, 0xa8, - 0xee, 0xee, }; - -#define GLYPH_icon_battery_left_WIDTH 4 + 0xee, 0xee, 0x7a, 0x56, 0xff, 0x3f, 0xee, 0xee, 0xee, 0xce, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0x65, 0xa8, 0xee, 0xee, 0xee, 0x01, 0xf9, 0xff, 0xff, 0x3f, 0xee, + 0xee, 0xee, 0xce, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x9f, + 0x10, 0xee, 0x1e, 0xf2, 0xff, 0xff, 0xff, 0x3f, 0xee, 0xee, 0xee, 0xce, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x2f, 0xe1, 0x0e, 0xff, 0xff, 0xff, 0xff, + 0x3f, 0xee, 0xee, 0xee, 0xce, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xe0, 0x9b, 0xff, 0xff, 0xff, 0xff, 0x3f, 0xee, 0xee, 0xee, 0xce, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xa9, 0xf7, 0xff, 0xff, + 0xff, 0xff, 0x3f, 0xee, 0xee, 0xee, 0xce, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0x7f, 0xf6, 0xff, 0xff, 0xff, 0xff, 0x3f, 0xee, 0xee, 0xee, 0xce, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x4f, 0xf5, + 0xff, 0xff, 0xff, 0xff, 0x3f, 0xee, 0xee, 0xee, 0xce, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xcf, 0xff, 0xff, 0xff, 0xff, 0xff, 0x3f, 0xee, 0xee, + 0xee, 0xce, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x3f, 0xee, 0xee, 0xee, 0xce, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x3f, + 0xee, 0xee, 0xee, 0xce, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0x4d, 0xee, 0xee, 0xee, 0xce, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xee, 0xee, 0xee, 0xee, + 0xee, 0xee, 0xee, 0xee, 0xee, 0xce, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xee, 0xee, 0xee, 0xee, 0xee, 0xee, 0xee, 0xee, 0xee, 0xce, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xee, 0xee, + 0xee, 0xee, 0xee, 0xee, 0xee, 0xee, 0xee, 0xce, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xee, 0xee, 0xee, 0xee, 0xee, 0xee, 0xee, 0xee, 0xee, + 0xce, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xee, 0xee, 0xee, 0xee, 0xee, 0xee, 0xee, 0xee, 0xee, 0xce, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xee, 0xee, 0xee, 0xee, 0xee, 0xee, 0xee, + 0xee, 0xee, 0xce, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xee, 0xee, 0xee, 0xee, 0xee, 0xee, 0xee, 0xee, 0xee, 0xce, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, + 0x4d, 0xee, 0xee, 0xee, 0xce, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x3f, 0xee, 0xee, 0xee, 0xce, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0x3f, 0xee, 0xee, 0xee, 0xce, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x3f, 0xee, 0xee, 0xee, 0xce, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0x3f, 0xee, 0xee, 0xee, 0xce, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x3f, 0xee, 0xee, + 0xee, 0xce, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x3f, 0xee, 0xee, 0xee, 0xce, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x3f, + 0xee, 0xee, 0xee, 0xce, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x3f, 0xee, 0xee, 0xee, 0xce, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0x3f, 0xee, 0xee, 0xee, 0xce, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x3f, 0xee, 0xee, 0xee, 0xce, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xdd, 0xdd, + 0xdd, 0xdd, 0xdd, 0x4d, 0xee, 0xee, 0xee, 0x3e, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, + 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xee, 0xee, 0xee, 0xee, 0xee, 0xee, 0xee, 0xee, 0xee, + 0xee, 0xee, 0xee, 0xee, 0xee, 0xee, 0xee, 0xee, 0xee, 0xee, 0xee, 0xee, 0xee, 0xee, 0xee, 0xee, + 0xee, 0xee, 0xee, 0xee, 0xee, 0xee, 0xee, 0xee, 0xee, 0xee, 0xee, 0xee, 0xee, 0xee, 0xee, 0xee, + 0xee, 0xee, 0xee, 0xee, 0xee, 0xee, 0xee, 0xee, 0xee, 0xee, 0xee, 0xee, 0xee, 0xee, 0xee, 0xee, + 0xee, 0xee, 0xee, 0xee, 0xee, 0xee, 0xee, 0xee, 0xee, 0xee, 0xee, 0xee, 0xee, 0xee, 0xee, 0xee, + 0xee, 0xee, 0xee, 0xee, 0xee, 0xee, 0xee, 0xee, 0xee, 0xee, 0xee, 0xee, 0xee, 0xee, 0xee, 0xee, + 0xee, 0xee, 0xee, 0xee, 0xee, 0xee, 0xee, 0xee, 0xee, 0xee, 0xee, 0xee, 0xee, 0xee, 0xee, 0xee, + 0xee, 0xee, 0xee, 0xee, 0xee, 0xee, 0xee, 0xee, 0xee, 0xee, 0xee, 0xee, 0xee, 0xee, 0xee, 0xee, + 0xee, 0xee, 0xee, 0xee, 0xee, 0xee, 0xee, 0xee, 0xee, 0xee, 0xee, 0xee, 0xee, 0xee, 0xee, 0xee, + 0xee, 0xee, 0xee, 0xee, 0xee, 0xee, 0xee, 0xee, 0xee, 0xee, 0xee, 0xee, 0xee, 0xee, 0xee, 0xee, + 0xee, 0xee, 0xee, 0xee, 0xee, 0xee, 0xee, 0xee, 0xee, 0xee, 0xee, 0xee, 0xee, 0xee, 0xee, 0xee, + 0xee, 0xee, 0xee, 0xee, 0xee, 0xee, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0x4d, 0xee, 0xee, 0xee, 0x3e, + 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xe3, 0xee, 0xee, 0xee, 0xd4, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xff, + 0xff, 0xff, 0xff, 0xff, 0x3f, 0xee, 0xee, 0xee, 0xce, 0xff, 0xff, 0xff, 0xff, 0xff, 0xec, 0xee, + 0xee, 0xee, 0xf3, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x3f, 0xee, 0xee, + 0xee, 0xce, 0xff, 0xff, 0xff, 0xff, 0xff, 0xec, 0xee, 0xee, 0xee, 0xf3, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x3f, 0xee, 0xee, 0xee, 0xce, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xec, 0xee, 0xee, 0xee, 0xf3, 0xff, 0xff, 0xff, 0xff, 0xff, 0xf9, 0xff, 0xff, 0xff, 0xff, 0x3f, + 0xee, 0xee, 0xee, 0xce, 0xff, 0xff, 0xff, 0xff, 0xff, 0xec, 0xee, 0xee, 0xee, 0xf3, 0xff, 0xff, + 0xff, 0xff, 0x5f, 0xf6, 0xff, 0xff, 0xff, 0xff, 0x3f, 0xee, 0xee, 0xee, 0xce, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xec, 0xee, 0xee, 0xee, 0xf3, 0xff, 0xff, 0xff, 0xff, 0x6f, 0xf7, 0xff, 0xff, 0xff, + 0xff, 0x3f, 0xee, 0xee, 0xee, 0xce, 0xff, 0xff, 0xff, 0xff, 0xff, 0xec, 0xee, 0xee, 0xee, 0xf3, + 0xff, 0xff, 0xff, 0xff, 0x8f, 0x9b, 0xff, 0xff, 0xff, 0xff, 0x3f, 0xee, 0xee, 0xee, 0xce, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xec, 0xee, 0xee, 0xee, 0xf3, 0xff, 0xff, 0xff, 0xff, 0xa9, 0x0e, 0xff, + 0xff, 0xff, 0xff, 0x3f, 0xee, 0xee, 0xee, 0xce, 0xff, 0xff, 0xff, 0xff, 0xff, 0xec, 0xee, 0xee, + 0xee, 0xf3, 0xff, 0xff, 0xff, 0xff, 0xe0, 0x1e, 0xf2, 0xff, 0xff, 0xff, 0x3f, 0xee, 0xee, 0xee, + 0xce, 0xff, 0xff, 0xff, 0xff, 0xff, 0xec, 0xee, 0xee, 0xee, 0xf3, 0xff, 0xff, 0xff, 0x2f, 0xe1, + 0xee, 0x01, 0xf9, 0xff, 0xff, 0x3f, 0xee, 0xee, 0xee, 0xce, 0xff, 0xff, 0xff, 0xff, 0xff, 0xec, + 0xee, 0xee, 0xee, 0xf3, 0xff, 0xff, 0x9f, 0x17, 0xee, 0xee, 0xee, 0x8a, 0x56, 0xff, 0x3f, 0xee, + 0xee, 0xee, 0xce, 0xff, 0xff, 0xff, 0xff, 0xff, 0xec, 0xee, 0xee, 0xee, 0xf3, 0xff, 0x65, 0xa8, + 0xee, 0xee, +}; + +#define GLYPH_icon_battery_left_WIDTH 4 #define GLYPH_icon_battery_left_HEIGHT 40 -#define GLYPH_icon_battery_left_BPP 2 +#define GLYPH_icon_battery_left_BPP 2 unsigned int const C_icon_battery_left_colors[] = { - 0x00000000, - 0x00454545, - 0x00606060, - 0x00666666, + 0x00000000, + 0x00454545, + 0x00606060, + 0x00666666, }; unsigned char const C_icon_battery_left_bitmap[] = { - 0x90, 0xf8, 0xfd, 0xfe, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 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, 0xfd, 0xf8, 0x90, }; + 0x90, 0xf8, 0xfd, 0xfe, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 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, 0xfd, 0xf8, 0x90, +}; -#define GLYPH_icon_battery_right_WIDTH 4 +#define GLYPH_icon_battery_right_WIDTH 4 #define GLYPH_icon_battery_right_HEIGHT 40 -#define GLYPH_icon_battery_right_BPP 2 +#define GLYPH_icon_battery_right_BPP 2 unsigned int const C_icon_battery_right_colors[] = { - 0x00000000, - 0x00101010, - 0x00454545, - 0x00666666, + 0x00000000, + 0x00101010, + 0x00454545, + 0x00666666, }; unsigned char const C_icon_battery_right_bitmap[] = { - 0x1b, 0x7f, 0xbf, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xbf, 0x7f, 0x1b, }; + 0x1b, 0x7f, 0xbf, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xbf, 0x7f, 0x1b, +}; -#define GLYPH_icon_lightning_WIDTH 17 +#define GLYPH_icon_lightning_WIDTH 17 #define GLYPH_icon_lightning_HEIGHT 24 -#define GLYPH_icon_lightning_BPP 4 +#define GLYPH_icon_lightning_BPP 4 unsigned int const C_icon_lightning_colors[] = { - 0x00fafafa, - 0x00f3f3f3, - 0x00e7e7e7, - 0x00bebebe, - 0x00797979, - 0x00d6d6d6, - 0x00b2b2b2, - 0x00636363, - 0x00494949, - 0x00373737, - 0x009c9c9c, - 0x008c8c8c, - 0x00232323, - 0x000c0c0c, - 0x00ffffff, - 0x00000000, + 0x00fafafa, + 0x00f3f3f3, + 0x00e7e7e7, + 0x00bebebe, + 0x00797979, + 0x00d6d6d6, + 0x00b2b2b2, + 0x00636363, + 0x00494949, + 0x00373737, + 0x009c9c9c, + 0x008c8c8c, + 0x00232323, + 0x000c0c0c, + 0x00ffffff, + 0x00000000, }; unsigned char const C_icon_lightning_bitmap[] = { - 0xfd, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfb, 0xff, 0xdd, 0xff, 0xff, 0xff, 0xff, 0xff, 0xaa, 0xff, - 0xdf, 0xfd, 0xff, 0xff, 0xff, 0xff, 0xea, 0xf8, 0xff, 0xdd, 0xff, 0xff, 0xff, 0xff, 0xeb, 0xd1, - 0xff, 0xdf, 0xfd, 0xff, 0xff, 0xff, 0xe4, 0x6e, 0xff, 0xff, 0xdd, 0xff, 0xff, 0xff, 0xe4, 0xee, - 0xf7, 0xff, 0xdf, 0xfd, 0xff, 0xff, 0xe7, 0xee, 0xce, 0xff, 0xff, 0xdd, 0xff, 0xff, 0x07, 0xee, - 0x5e, 0xff, 0xff, 0xdf, 0xfd, 0xff, 0x08, 0xee, 0xee, 0xfb, 0xff, 0xff, 0xdd, 0xff, 0x08, 0xee, - 0xee, 0x7e, 0xcc, 0xcc, 0xcc, 0xfd, 0x19, 0xee, 0xee, 0xee, 0xee, 0xee, 0xee, 0xd6, 0x19, 0xee, - 0xee, 0xee, 0xee, 0xee, 0xee, 0xd3, 0x29, 0xee, 0xee, 0xee, 0xee, 0xee, 0xee, 0xd3, 0xad, 0x33, - 0x33, 0x53, 0xee, 0xee, 0xee, 0xd5, 0xdf, 0xfd, 0xff, 0xff, 0xe8, 0xee, 0xee, 0xc2, 0xff, 0xdd, - 0xff, 0xff, 0xbf, 0xee, 0xee, 0xc2, 0xff, 0xdf, 0xfd, 0xff, 0xff, 0xe5, 0xee, 0x91, 0xff, 0xff, - 0xdd, 0xff, 0xff, 0xec, 0xee, 0x91, 0xff, 0xff, 0xdf, 0xfd, 0xff, 0x4f, 0xee, 0x80, 0xff, 0xff, - 0xff, 0xdd, 0xff, 0xff, 0xe3, 0x7e, 0xff, 0xff, 0xff, 0xdf, 0xfd, 0xff, 0xed, 0x7e, 0xff, 0xff, - 0xff, 0xff, 0xdd, 0xff, 0x7f, 0x4e, 0xff, 0xff, 0xff, 0xff, 0xdf, 0xfd, 0xff, 0xb6, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xdd, 0xff, 0xbf, 0xff, 0xff, 0xff, 0xff, 0xff, 0xdf, }; - -#define GLYPH_icon_plug_WIDTH 24 + 0xfd, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfb, 0xff, 0xdd, 0xff, 0xff, 0xff, 0xff, 0xff, 0xaa, 0xff, + 0xdf, 0xfd, 0xff, 0xff, 0xff, 0xff, 0xea, 0xf8, 0xff, 0xdd, 0xff, 0xff, 0xff, 0xff, 0xeb, 0xd1, + 0xff, 0xdf, 0xfd, 0xff, 0xff, 0xff, 0xe4, 0x6e, 0xff, 0xff, 0xdd, 0xff, 0xff, 0xff, 0xe4, 0xee, + 0xf7, 0xff, 0xdf, 0xfd, 0xff, 0xff, 0xe7, 0xee, 0xce, 0xff, 0xff, 0xdd, 0xff, 0xff, 0x07, 0xee, + 0x5e, 0xff, 0xff, 0xdf, 0xfd, 0xff, 0x08, 0xee, 0xee, 0xfb, 0xff, 0xff, 0xdd, 0xff, 0x08, 0xee, + 0xee, 0x7e, 0xcc, 0xcc, 0xcc, 0xfd, 0x19, 0xee, 0xee, 0xee, 0xee, 0xee, 0xee, 0xd6, 0x19, 0xee, + 0xee, 0xee, 0xee, 0xee, 0xee, 0xd3, 0x29, 0xee, 0xee, 0xee, 0xee, 0xee, 0xee, 0xd3, 0xad, 0x33, + 0x33, 0x53, 0xee, 0xee, 0xee, 0xd5, 0xdf, 0xfd, 0xff, 0xff, 0xe8, 0xee, 0xee, 0xc2, 0xff, 0xdd, + 0xff, 0xff, 0xbf, 0xee, 0xee, 0xc2, 0xff, 0xdf, 0xfd, 0xff, 0xff, 0xe5, 0xee, 0x91, 0xff, 0xff, + 0xdd, 0xff, 0xff, 0xec, 0xee, 0x91, 0xff, 0xff, 0xdf, 0xfd, 0xff, 0x4f, 0xee, 0x80, 0xff, 0xff, + 0xff, 0xdd, 0xff, 0xff, 0xe3, 0x7e, 0xff, 0xff, 0xff, 0xdf, 0xfd, 0xff, 0xed, 0x7e, 0xff, 0xff, + 0xff, 0xff, 0xdd, 0xff, 0x7f, 0x4e, 0xff, 0xff, 0xff, 0xff, 0xdf, 0xfd, 0xff, 0xb6, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xdd, 0xff, 0xbf, 0xff, 0xff, 0xff, 0xff, 0xff, 0xdf, +}; + +#define GLYPH_icon_plug_WIDTH 24 #define GLYPH_icon_plug_HEIGHT 15 -#define GLYPH_icon_plug_BPP 4 +#define GLYPH_icon_plug_BPP 4 unsigned int const C_icon_plug_colors[] = { - 0x00fafafa, - 0x00595959, - 0x00f3f3f3, - 0x00282828, - 0x00d6d6d6, - 0x008a8a8a, - 0x00777777, - 0x00838383, - 0x001b1b1b, - 0x00dfdfdf, - 0x00a7a7a7, - 0x00eaeaea, - 0x00b2b2b2, - 0x00888888, - 0x00ffffff, - 0x00000000, + 0x00fafafa, + 0x00595959, + 0x00f3f3f3, + 0x00282828, + 0x00d6d6d6, + 0x008a8a8a, + 0x00777777, + 0x00838383, + 0x001b1b1b, + 0x00dfdfdf, + 0x00a7a7a7, + 0x00eaeaea, + 0x00b2b2b2, + 0x00888888, + 0x00ffffff, + 0x00000000, }; unsigned char const C_icon_plug_bitmap[] = { - 0xff, 0xff, 0xff, 0xff, 0xff, 0x58, 0x24, 0xee, 0xf1, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0x1f, 0xe2, 0xee, 0xee, 0xf1, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xe1, 0xee, 0xee, 0xee, - 0x6a, 0x66, 0x66, 0x36, 0xff, 0xff, 0xff, 0x8f, 0xe2, 0xee, 0xee, 0xee, 0xee, 0xee, 0xee, 0x9e, - 0xff, 0xff, 0xff, 0x5f, 0xee, 0xee, 0xee, 0xee, 0xee, 0xee, 0xee, 0x9e, 0xff, 0xff, 0xff, 0x4f, - 0xee, 0xee, 0xee, 0xee, 0xdc, 0xdd, 0xdd, 0x37, 0xb3, 0xee, 0xee, 0xee, 0xee, 0xee, 0xee, 0xee, - 0xf1, 0xff, 0xff, 0xff, 0xe4, 0xee, 0xee, 0xee, 0xee, 0xee, 0xee, 0xee, 0xf1, 0xff, 0xff, 0xff, - 0xb3, 0xee, 0xee, 0xee, 0xee, 0xee, 0xee, 0xee, 0xf1, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x4f, - 0xee, 0xee, 0xee, 0xee, 0xdc, 0xdd, 0xdd, 0x37, 0xff, 0xff, 0xff, 0x5f, 0xee, 0xee, 0xee, 0xee, - 0xee, 0xee, 0xee, 0x9e, 0xff, 0xff, 0xff, 0x8f, 0xe2, 0xee, 0xee, 0xee, 0xee, 0xee, 0xee, 0x9e, - 0xff, 0xff, 0xff, 0xff, 0x01, 0xee, 0xee, 0xee, 0x6a, 0xdd, 0xdd, 0x37, 0xff, 0xff, 0xff, 0xff, - 0x1f, 0xe2, 0xee, 0xee, 0xf1, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x58, 0x04, 0xee, - 0xf1, 0xff, 0xff, 0xff, }; - - -#define GLYPH_badge_download_blue_WIDTH 50 + 0xff, 0xff, 0xff, 0xff, 0xff, 0x58, 0x24, 0xee, 0xf1, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0x1f, 0xe2, 0xee, 0xee, 0xf1, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xe1, 0xee, + 0xee, 0xee, 0x6a, 0x66, 0x66, 0x36, 0xff, 0xff, 0xff, 0x8f, 0xe2, 0xee, 0xee, 0xee, 0xee, + 0xee, 0xee, 0x9e, 0xff, 0xff, 0xff, 0x5f, 0xee, 0xee, 0xee, 0xee, 0xee, 0xee, 0xee, 0x9e, + 0xff, 0xff, 0xff, 0x4f, 0xee, 0xee, 0xee, 0xee, 0xdc, 0xdd, 0xdd, 0x37, 0xb3, 0xee, 0xee, + 0xee, 0xee, 0xee, 0xee, 0xee, 0xf1, 0xff, 0xff, 0xff, 0xe4, 0xee, 0xee, 0xee, 0xee, 0xee, + 0xee, 0xee, 0xf1, 0xff, 0xff, 0xff, 0xb3, 0xee, 0xee, 0xee, 0xee, 0xee, 0xee, 0xee, 0xf1, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x4f, 0xee, 0xee, 0xee, 0xee, 0xdc, 0xdd, 0xdd, 0x37, + 0xff, 0xff, 0xff, 0x5f, 0xee, 0xee, 0xee, 0xee, 0xee, 0xee, 0xee, 0x9e, 0xff, 0xff, 0xff, + 0x8f, 0xe2, 0xee, 0xee, 0xee, 0xee, 0xee, 0xee, 0x9e, 0xff, 0xff, 0xff, 0xff, 0x01, 0xee, + 0xee, 0xee, 0x6a, 0xdd, 0xdd, 0x37, 0xff, 0xff, 0xff, 0xff, 0x1f, 0xe2, 0xee, 0xee, 0xf1, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x58, 0x04, 0xee, 0xf1, 0xff, 0xff, 0xff, +}; + +#define GLYPH_badge_download_blue_WIDTH 50 #define GLYPH_badge_download_blue_HEIGHT 50 -#define GLYPH_badge_download_blue_BPP 2 +#define GLYPH_badge_download_blue_BPP 2 unsigned int const C_badge_download_blue_colors[] = { - 0x00cccccc, - 0x00dddddd, - 0x00ededed, - 0x00f9f9f9, + 0x00cccccc, + 0x00dddddd, + 0x00ededed, + 0x00f9f9f9, }; unsigned char const C_badge_download_blue_bitmap[] = { - 0xff, 0xff, 0xff, 0xff, 0xaf, 0x05, 0x00, 0xe5, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0x5f, 0x00, 0x00, 0x00, 0x40, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x1b, 0x00, 0x00, 0x00, - 0x00, 0x40, 0xfe, 0xff, 0xff, 0xff, 0xff, 0xff, 0x1f, 0x00, 0x94, 0xfe, 0x6b, 0x01, 0x40, 0xff, - 0xff, 0xff, 0xff, 0xff, 0x2f, 0x00, 0xf9, 0xff, 0xff, 0xff, 0x06, 0x80, 0xff, 0xff, 0xff, 0xff, - 0x7f, 0x00, 0xf9, 0xff, 0xff, 0xff, 0xff, 0x06, 0xd0, 0xff, 0xff, 0xff, 0xff, 0x01, 0xf8, 0xff, - 0xff, 0xff, 0xff, 0xff, 0x02, 0xf4, 0xff, 0xff, 0xff, 0x07, 0xf4, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0x01, 0xfd, 0xff, 0xff, 0x1f, 0xd0, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x7f, 0x40, 0xff, - 0xff, 0x7f, 0x80, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x2f, 0xd0, 0xff, 0xff, 0x02, 0xfd, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x07, 0xf8, 0xff, 0x0f, 0xf4, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0x01, 0xff, 0x7f, 0xc0, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0x3f, 0xd0, 0xff, 0x02, 0xfe, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x0b, 0xf8, 0x1f, - 0xf4, 0xff, 0xff, 0xff, 0x2f, 0x80, 0xff, 0xff, 0xff, 0xff, 0x41, 0xff, 0x80, 0xff, 0xff, 0xff, - 0xff, 0x01, 0xf4, 0xff, 0xff, 0xff, 0x2f, 0xf0, 0x07, 0xfd, 0xff, 0xff, 0xff, 0x1f, 0x40, 0xff, - 0xff, 0xff, 0xff, 0x07, 0x3d, 0xe0, 0xff, 0xff, 0xff, 0xff, 0x01, 0xf4, 0xff, 0xff, 0xff, 0xbf, - 0xc0, 0x03, 0xff, 0xff, 0xff, 0xff, 0x1f, 0x40, 0xff, 0xff, 0xff, 0xff, 0x0f, 0x2c, 0xf4, 0xff, - 0xff, 0xff, 0xff, 0x01, 0xf4, 0xff, 0xff, 0xff, 0xff, 0x81, 0x41, 0xff, 0xff, 0xff, 0xbf, 0x1a, - 0x40, 0xaa, 0xff, 0xff, 0xff, 0x1f, 0x14, 0xf8, 0xff, 0xff, 0xff, 0x01, 0x00, 0x00, 0xf4, 0xff, - 0xff, 0xff, 0x42, 0x80, 0xff, 0xff, 0xff, 0x2f, 0x00, 0x00, 0x80, 0xff, 0xff, 0xff, 0x2f, 0x00, - 0xfc, 0xff, 0xff, 0xff, 0x0b, 0x00, 0x00, 0xfe, 0xff, 0xff, 0xff, 0x03, 0xc0, 0xff, 0xff, 0xff, - 0xff, 0x02, 0x00, 0xf8, 0xff, 0xff, 0xff, 0x3f, 0x00, 0xfc, 0xff, 0xff, 0xff, 0xbf, 0x00, 0xe0, - 0xff, 0xff, 0xff, 0xff, 0x03, 0xc0, 0xff, 0xff, 0xff, 0xff, 0x2f, 0x80, 0xff, 0xff, 0xff, 0xff, - 0x3f, 0x00, 0xf8, 0xff, 0xff, 0xff, 0xff, 0x0b, 0xfe, 0xff, 0xff, 0xff, 0xff, 0x02, 0x81, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x2f, 0x14, 0xf4, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x41, 0x42, 0xff, 0xff, 0x1f, 0x00, 0x00, 0x00, 0x00, 0x40, - 0xff, 0xff, 0x1f, 0x38, 0xf0, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf0, 0xff, 0xff, 0xc0, - 0x03, 0xfe, 0xff, 0x0f, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0x0b, 0x7c, 0xd0, 0xff, 0xff, - 0x01, 0x00, 0x00, 0x00, 0x00, 0xf4, 0xff, 0x7f, 0xd0, 0x0f, 0xf8, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0x02, 0xff, 0x41, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0x1f, 0xf4, 0x2f, 0xe0, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xbf, 0x80, 0xff, 0x07, - 0xfc, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x03, 0xfd, 0xff, 0x40, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0x1f, 0xf0, 0xff, 0x2f, 0xd0, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0x7f, 0x80, 0xff, 0xff, 0x07, 0xf8, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x02, 0xfd, - 0xff, 0xff, 0x01, 0xfd, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x07, 0xf4, 0xff, 0xff, 0x7f, 0x40, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x1f, 0xd0, 0xff, 0xff, 0xff, 0x1f, 0x80, 0xff, 0xff, 0xff, - 0xff, 0xff, 0x2f, 0x40, 0xff, 0xff, 0xff, 0xff, 0x07, 0x90, 0xff, 0xff, 0xff, 0xff, 0x6f, 0x00, - 0xfd, 0xff, 0xff, 0xff, 0xff, 0x02, 0x90, 0xff, 0xff, 0xff, 0x6f, 0x00, 0xf8, 0xff, 0xff, 0xff, - 0xff, 0xff, 0x01, 0x40, 0xe9, 0xbf, 0x16, 0x00, 0xf4, 0xff, 0xff, 0xff, 0xff, 0xff, 0xbf, 0x01, - 0x00, 0x00, 0x00, 0x00, 0xe4, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x01, 0x00, 0x00, 0x00, - 0xf4, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x5a, 0x00, 0x50, 0xfa, 0xff, 0xff, 0xff, - 0xff, }; - -#define GLYPH_badge_warning_blue_WIDTH 50 + 0xff, 0xff, 0xff, 0xff, 0xaf, 0x05, 0x00, 0xe5, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0x5f, 0x00, 0x00, 0x00, 0x40, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x1b, 0x00, 0x00, 0x00, + 0x00, 0x40, 0xfe, 0xff, 0xff, 0xff, 0xff, 0xff, 0x1f, 0x00, 0x94, 0xfe, 0x6b, 0x01, 0x40, 0xff, + 0xff, 0xff, 0xff, 0xff, 0x2f, 0x00, 0xf9, 0xff, 0xff, 0xff, 0x06, 0x80, 0xff, 0xff, 0xff, 0xff, + 0x7f, 0x00, 0xf9, 0xff, 0xff, 0xff, 0xff, 0x06, 0xd0, 0xff, 0xff, 0xff, 0xff, 0x01, 0xf8, 0xff, + 0xff, 0xff, 0xff, 0xff, 0x02, 0xf4, 0xff, 0xff, 0xff, 0x07, 0xf4, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0x01, 0xfd, 0xff, 0xff, 0x1f, 0xd0, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x7f, 0x40, 0xff, + 0xff, 0x7f, 0x80, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x2f, 0xd0, 0xff, 0xff, 0x02, 0xfd, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x07, 0xf8, 0xff, 0x0f, 0xf4, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0x01, 0xff, 0x7f, 0xc0, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0x3f, 0xd0, 0xff, 0x02, 0xfe, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x0b, 0xf8, 0x1f, + 0xf4, 0xff, 0xff, 0xff, 0x2f, 0x80, 0xff, 0xff, 0xff, 0xff, 0x41, 0xff, 0x80, 0xff, 0xff, 0xff, + 0xff, 0x01, 0xf4, 0xff, 0xff, 0xff, 0x2f, 0xf0, 0x07, 0xfd, 0xff, 0xff, 0xff, 0x1f, 0x40, 0xff, + 0xff, 0xff, 0xff, 0x07, 0x3d, 0xe0, 0xff, 0xff, 0xff, 0xff, 0x01, 0xf4, 0xff, 0xff, 0xff, 0xbf, + 0xc0, 0x03, 0xff, 0xff, 0xff, 0xff, 0x1f, 0x40, 0xff, 0xff, 0xff, 0xff, 0x0f, 0x2c, 0xf4, 0xff, + 0xff, 0xff, 0xff, 0x01, 0xf4, 0xff, 0xff, 0xff, 0xff, 0x81, 0x41, 0xff, 0xff, 0xff, 0xbf, 0x1a, + 0x40, 0xaa, 0xff, 0xff, 0xff, 0x1f, 0x14, 0xf8, 0xff, 0xff, 0xff, 0x01, 0x00, 0x00, 0xf4, 0xff, + 0xff, 0xff, 0x42, 0x80, 0xff, 0xff, 0xff, 0x2f, 0x00, 0x00, 0x80, 0xff, 0xff, 0xff, 0x2f, 0x00, + 0xfc, 0xff, 0xff, 0xff, 0x0b, 0x00, 0x00, 0xfe, 0xff, 0xff, 0xff, 0x03, 0xc0, 0xff, 0xff, 0xff, + 0xff, 0x02, 0x00, 0xf8, 0xff, 0xff, 0xff, 0x3f, 0x00, 0xfc, 0xff, 0xff, 0xff, 0xbf, 0x00, 0xe0, + 0xff, 0xff, 0xff, 0xff, 0x03, 0xc0, 0xff, 0xff, 0xff, 0xff, 0x2f, 0x80, 0xff, 0xff, 0xff, 0xff, + 0x3f, 0x00, 0xf8, 0xff, 0xff, 0xff, 0xff, 0x0b, 0xfe, 0xff, 0xff, 0xff, 0xff, 0x02, 0x81, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x2f, 0x14, 0xf4, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x41, 0x42, 0xff, 0xff, 0x1f, 0x00, 0x00, 0x00, 0x00, 0x40, + 0xff, 0xff, 0x1f, 0x38, 0xf0, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf0, 0xff, 0xff, 0xc0, + 0x03, 0xfe, 0xff, 0x0f, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0x0b, 0x7c, 0xd0, 0xff, 0xff, + 0x01, 0x00, 0x00, 0x00, 0x00, 0xf4, 0xff, 0x7f, 0xd0, 0x0f, 0xf8, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0x02, 0xff, 0x41, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0x1f, 0xf4, 0x2f, 0xe0, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xbf, 0x80, 0xff, 0x07, + 0xfc, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x03, 0xfd, 0xff, 0x40, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0x1f, 0xf0, 0xff, 0x2f, 0xd0, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0x7f, 0x80, 0xff, 0xff, 0x07, 0xf8, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x02, 0xfd, + 0xff, 0xff, 0x01, 0xfd, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x07, 0xf4, 0xff, 0xff, 0x7f, 0x40, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x1f, 0xd0, 0xff, 0xff, 0xff, 0x1f, 0x80, 0xff, 0xff, 0xff, + 0xff, 0xff, 0x2f, 0x40, 0xff, 0xff, 0xff, 0xff, 0x07, 0x90, 0xff, 0xff, 0xff, 0xff, 0x6f, 0x00, + 0xfd, 0xff, 0xff, 0xff, 0xff, 0x02, 0x90, 0xff, 0xff, 0xff, 0x6f, 0x00, 0xf8, 0xff, 0xff, 0xff, + 0xff, 0xff, 0x01, 0x40, 0xe9, 0xbf, 0x16, 0x00, 0xf4, 0xff, 0xff, 0xff, 0xff, 0xff, 0xbf, 0x01, + 0x00, 0x00, 0x00, 0x00, 0xe4, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x01, 0x00, 0x00, 0x00, + 0xf4, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x5a, 0x00, 0x50, 0xfa, 0xff, 0xff, 0xff, + 0xff, +}; + +#define GLYPH_badge_warning_blue_WIDTH 50 #define GLYPH_badge_warning_blue_HEIGHT 50 -#define GLYPH_badge_warning_blue_BPP 2 +#define GLYPH_badge_warning_blue_BPP 2 unsigned int const C_badge_warning_blue_colors[] = { - 0x00cccccc, - 0x00dddddd, - 0x00eeeeee, - 0x00f9f9f9, + 0x00cccccc, + 0x00dddddd, + 0x00eeeeee, + 0x00f9f9f9, }; unsigned char const C_badge_warning_blue_bitmap[] = { - 0xff, 0xff, 0xff, 0xff, 0xaf, 0x05, 0x00, 0xe5, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0x5f, 0x00, 0x00, 0x00, 0x40, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x1b, 0x00, 0x00, 0x00, - 0x00, 0x40, 0xfe, 0xff, 0xff, 0xff, 0xff, 0xff, 0x1f, 0x00, 0x94, 0xfe, 0x6b, 0x01, 0x40, 0xff, - 0xff, 0xff, 0xff, 0xff, 0x2f, 0x00, 0xf9, 0xff, 0xff, 0xff, 0x06, 0x80, 0xff, 0xff, 0xff, 0xff, - 0x7f, 0x00, 0xf9, 0xff, 0xff, 0xff, 0xff, 0x06, 0xd0, 0xff, 0xff, 0xff, 0xff, 0x01, 0xf8, 0xff, - 0xff, 0xff, 0xff, 0xff, 0x02, 0xf4, 0xff, 0xff, 0xff, 0x07, 0xf4, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0x01, 0xfd, 0xff, 0xff, 0x1f, 0xd0, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x7f, 0x40, 0xff, - 0xff, 0x7f, 0x80, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x2f, 0xd0, 0xff, 0xff, 0x02, 0xfd, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x07, 0xf8, 0xff, 0x0f, 0xf4, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0x01, 0xff, 0x7f, 0xc0, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0x3f, 0xd0, 0xff, 0x02, 0xfe, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x0b, 0xf8, 0x1f, - 0xf4, 0xff, 0xff, 0xff, 0x3f, 0xc0, 0xff, 0xff, 0xff, 0xff, 0x41, 0xff, 0x80, 0xff, 0xff, 0xff, - 0xff, 0x03, 0xfc, 0xff, 0xff, 0xff, 0x2f, 0xf0, 0x07, 0xfd, 0xff, 0xff, 0xff, 0x3f, 0xc0, 0xff, - 0xff, 0xff, 0xff, 0x07, 0x3d, 0xe0, 0xff, 0xff, 0xff, 0xff, 0x03, 0xfc, 0xff, 0xff, 0xff, 0xbf, - 0xc0, 0x03, 0xff, 0xff, 0xff, 0xff, 0x3f, 0xc0, 0xff, 0xff, 0xff, 0xff, 0x0f, 0x2c, 0xf4, 0xff, - 0xff, 0xff, 0xff, 0x03, 0xfc, 0xff, 0xff, 0xff, 0xff, 0x81, 0x41, 0xff, 0xff, 0xff, 0xff, 0x3f, - 0xc0, 0xff, 0xff, 0xff, 0xff, 0x1f, 0x14, 0xf8, 0xff, 0xff, 0xff, 0xff, 0x03, 0xfc, 0xff, 0xff, - 0xff, 0xff, 0x42, 0x80, 0xff, 0xff, 0xff, 0xff, 0x3f, 0xc0, 0xff, 0xff, 0xff, 0xff, 0x2f, 0x00, - 0xfc, 0xff, 0xff, 0xff, 0xff, 0x03, 0xfc, 0xff, 0xff, 0xff, 0xff, 0x03, 0xc0, 0xff, 0xff, 0xff, - 0xff, 0x3f, 0xc0, 0xff, 0xff, 0xff, 0xff, 0x3f, 0x00, 0xfc, 0xff, 0xff, 0xff, 0xff, 0x03, 0xfc, - 0xff, 0xff, 0xff, 0xff, 0x03, 0xc0, 0xff, 0xff, 0xff, 0xff, 0x3f, 0xc0, 0xff, 0xff, 0xff, 0xff, - 0x3f, 0x00, 0xf8, 0xff, 0xff, 0xff, 0xff, 0xab, 0xfe, 0xff, 0xff, 0xff, 0xff, 0x02, 0x81, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x2f, 0x14, 0xf4, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x41, 0x42, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0x1f, 0x38, 0xf0, 0xff, 0xff, 0xff, 0xff, 0xab, 0xfe, 0xff, 0xff, 0xff, 0xff, 0xc0, - 0x03, 0xfe, 0xff, 0xff, 0xff, 0x3f, 0xc0, 0xff, 0xff, 0xff, 0xff, 0x0b, 0x7c, 0xd0, 0xff, 0xff, - 0xff, 0xff, 0x03, 0xfc, 0xff, 0xff, 0xff, 0x7f, 0xd0, 0x0f, 0xf8, 0xff, 0xff, 0xff, 0x3f, 0xc0, - 0xff, 0xff, 0xff, 0xff, 0x02, 0xff, 0x41, 0xff, 0xff, 0xff, 0xff, 0x03, 0xfc, 0xff, 0xff, 0xff, - 0x1f, 0xf4, 0x2f, 0xe0, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xbf, 0x80, 0xff, 0x07, - 0xfc, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x03, 0xfd, 0xff, 0x40, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0x1f, 0xf0, 0xff, 0x2f, 0xd0, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0x7f, 0x80, 0xff, 0xff, 0x07, 0xf8, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x02, 0xfd, - 0xff, 0xff, 0x01, 0xfd, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x07, 0xf4, 0xff, 0xff, 0x7f, 0x40, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x1f, 0xd0, 0xff, 0xff, 0xff, 0x1f, 0x80, 0xff, 0xff, 0xff, - 0xff, 0xff, 0x2f, 0x40, 0xff, 0xff, 0xff, 0xff, 0x07, 0x90, 0xff, 0xff, 0xff, 0xff, 0x6f, 0x00, - 0xfd, 0xff, 0xff, 0xff, 0xff, 0x02, 0x90, 0xff, 0xff, 0xff, 0x6f, 0x00, 0xf8, 0xff, 0xff, 0xff, - 0xff, 0xff, 0x01, 0x40, 0xe9, 0xbf, 0x16, 0x00, 0xf4, 0xff, 0xff, 0xff, 0xff, 0xff, 0xbf, 0x01, - 0x00, 0x00, 0x00, 0x00, 0xe4, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x01, 0x00, 0x00, 0x00, - 0xf4, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x5a, 0x00, 0x50, 0xfa, 0xff, 0xff, 0xff, - 0xff, }; - -#define GLYPH_loader_blue_WIDTH 50 + 0xff, 0xff, 0xff, 0xff, 0xaf, 0x05, 0x00, 0xe5, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0x5f, 0x00, 0x00, 0x00, 0x40, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x1b, 0x00, 0x00, 0x00, + 0x00, 0x40, 0xfe, 0xff, 0xff, 0xff, 0xff, 0xff, 0x1f, 0x00, 0x94, 0xfe, 0x6b, 0x01, 0x40, 0xff, + 0xff, 0xff, 0xff, 0xff, 0x2f, 0x00, 0xf9, 0xff, 0xff, 0xff, 0x06, 0x80, 0xff, 0xff, 0xff, 0xff, + 0x7f, 0x00, 0xf9, 0xff, 0xff, 0xff, 0xff, 0x06, 0xd0, 0xff, 0xff, 0xff, 0xff, 0x01, 0xf8, 0xff, + 0xff, 0xff, 0xff, 0xff, 0x02, 0xf4, 0xff, 0xff, 0xff, 0x07, 0xf4, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0x01, 0xfd, 0xff, 0xff, 0x1f, 0xd0, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x7f, 0x40, 0xff, + 0xff, 0x7f, 0x80, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x2f, 0xd0, 0xff, 0xff, 0x02, 0xfd, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x07, 0xf8, 0xff, 0x0f, 0xf4, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0x01, 0xff, 0x7f, 0xc0, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0x3f, 0xd0, 0xff, 0x02, 0xfe, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x0b, 0xf8, 0x1f, + 0xf4, 0xff, 0xff, 0xff, 0x3f, 0xc0, 0xff, 0xff, 0xff, 0xff, 0x41, 0xff, 0x80, 0xff, 0xff, 0xff, + 0xff, 0x03, 0xfc, 0xff, 0xff, 0xff, 0x2f, 0xf0, 0x07, 0xfd, 0xff, 0xff, 0xff, 0x3f, 0xc0, 0xff, + 0xff, 0xff, 0xff, 0x07, 0x3d, 0xe0, 0xff, 0xff, 0xff, 0xff, 0x03, 0xfc, 0xff, 0xff, 0xff, 0xbf, + 0xc0, 0x03, 0xff, 0xff, 0xff, 0xff, 0x3f, 0xc0, 0xff, 0xff, 0xff, 0xff, 0x0f, 0x2c, 0xf4, 0xff, + 0xff, 0xff, 0xff, 0x03, 0xfc, 0xff, 0xff, 0xff, 0xff, 0x81, 0x41, 0xff, 0xff, 0xff, 0xff, 0x3f, + 0xc0, 0xff, 0xff, 0xff, 0xff, 0x1f, 0x14, 0xf8, 0xff, 0xff, 0xff, 0xff, 0x03, 0xfc, 0xff, 0xff, + 0xff, 0xff, 0x42, 0x80, 0xff, 0xff, 0xff, 0xff, 0x3f, 0xc0, 0xff, 0xff, 0xff, 0xff, 0x2f, 0x00, + 0xfc, 0xff, 0xff, 0xff, 0xff, 0x03, 0xfc, 0xff, 0xff, 0xff, 0xff, 0x03, 0xc0, 0xff, 0xff, 0xff, + 0xff, 0x3f, 0xc0, 0xff, 0xff, 0xff, 0xff, 0x3f, 0x00, 0xfc, 0xff, 0xff, 0xff, 0xff, 0x03, 0xfc, + 0xff, 0xff, 0xff, 0xff, 0x03, 0xc0, 0xff, 0xff, 0xff, 0xff, 0x3f, 0xc0, 0xff, 0xff, 0xff, 0xff, + 0x3f, 0x00, 0xf8, 0xff, 0xff, 0xff, 0xff, 0xab, 0xfe, 0xff, 0xff, 0xff, 0xff, 0x02, 0x81, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x2f, 0x14, 0xf4, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x41, 0x42, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0x1f, 0x38, 0xf0, 0xff, 0xff, 0xff, 0xff, 0xab, 0xfe, 0xff, 0xff, 0xff, 0xff, 0xc0, + 0x03, 0xfe, 0xff, 0xff, 0xff, 0x3f, 0xc0, 0xff, 0xff, 0xff, 0xff, 0x0b, 0x7c, 0xd0, 0xff, 0xff, + 0xff, 0xff, 0x03, 0xfc, 0xff, 0xff, 0xff, 0x7f, 0xd0, 0x0f, 0xf8, 0xff, 0xff, 0xff, 0x3f, 0xc0, + 0xff, 0xff, 0xff, 0xff, 0x02, 0xff, 0x41, 0xff, 0xff, 0xff, 0xff, 0x03, 0xfc, 0xff, 0xff, 0xff, + 0x1f, 0xf4, 0x2f, 0xe0, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xbf, 0x80, 0xff, 0x07, + 0xfc, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x03, 0xfd, 0xff, 0x40, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0x1f, 0xf0, 0xff, 0x2f, 0xd0, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0x7f, 0x80, 0xff, 0xff, 0x07, 0xf8, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x02, 0xfd, + 0xff, 0xff, 0x01, 0xfd, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x07, 0xf4, 0xff, 0xff, 0x7f, 0x40, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x1f, 0xd0, 0xff, 0xff, 0xff, 0x1f, 0x80, 0xff, 0xff, 0xff, + 0xff, 0xff, 0x2f, 0x40, 0xff, 0xff, 0xff, 0xff, 0x07, 0x90, 0xff, 0xff, 0xff, 0xff, 0x6f, 0x00, + 0xfd, 0xff, 0xff, 0xff, 0xff, 0x02, 0x90, 0xff, 0xff, 0xff, 0x6f, 0x00, 0xf8, 0xff, 0xff, 0xff, + 0xff, 0xff, 0x01, 0x40, 0xe9, 0xbf, 0x16, 0x00, 0xf4, 0xff, 0xff, 0xff, 0xff, 0xff, 0xbf, 0x01, + 0x00, 0x00, 0x00, 0x00, 0xe4, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x01, 0x00, 0x00, 0x00, + 0xf4, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x5a, 0x00, 0x50, 0xfa, 0xff, 0xff, 0xff, + 0xff, +}; + +#define GLYPH_loader_blue_WIDTH 50 #define GLYPH_loader_blue_HEIGHT 50 -#define GLYPH_loader_blue_BPP 2 +#define GLYPH_loader_blue_BPP 2 unsigned int const C_loader_blue_colors[] = { - 0x00cccccc, - 0x00dddddd, - 0x00ededed, - 0x00f9f9f9, + 0x00cccccc, + 0x00dddddd, + 0x00ededed, + 0x00f9f9f9, }; unsigned char const C_loader_blue_bitmap[] = { - 0xff, 0xff, 0xff, 0xff, 0xbf, 0x05, 0x00, 0xe5, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0x1f, 0x00, 0x00, 0x00, 0x40, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x1b, 0x00, 0x00, 0x00, - 0x00, 0x40, 0xfe, 0xff, 0xff, 0xff, 0xff, 0xff, 0x1f, 0x00, 0x94, 0xfe, 0x6b, 0x01, 0x40, 0xff, - 0xff, 0xff, 0xff, 0xff, 0x2f, 0x00, 0xf9, 0xff, 0xff, 0xff, 0x06, 0x80, 0xff, 0xff, 0xff, 0xff, - 0x7f, 0x00, 0xf9, 0xff, 0xff, 0xff, 0xff, 0x06, 0xd0, 0xff, 0xff, 0xff, 0xff, 0x01, 0xf8, 0xff, - 0xff, 0xff, 0xff, 0xff, 0x02, 0xf4, 0xff, 0xff, 0xff, 0x07, 0xf4, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0x01, 0xfd, 0xff, 0xff, 0x1f, 0xd0, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x7f, 0x40, 0xff, - 0xff, 0x7f, 0x80, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x2f, 0xd0, 0xff, 0xff, 0x02, 0xfd, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x07, 0xf8, 0xff, 0x0f, 0xf4, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0x01, 0xff, 0x7f, 0xc0, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0x3f, 0xd0, 0xff, 0x02, 0xfe, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x0b, 0xf8, 0x1f, - 0xf4, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x41, 0xff, 0x80, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x2f, 0xe0, 0x07, 0xfd, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0x07, 0x3d, 0xe0, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xbf, - 0xc0, 0x03, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x0f, 0x28, 0xf4, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x81, 0x41, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0x1f, 0x14, 0xf8, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0x42, 0x80, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x2f, 0x00, - 0xfc, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x03, 0xc0, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x3f, 0x00, 0xfc, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xc0, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0x0f, 0xf8, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x81, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x1f, 0xf4, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x42, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0x3f, 0xf0, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0x03, 0xfe, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x7f, 0xd0, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x0b, 0xf8, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x41, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0x2f, 0xe0, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x07, - 0xfc, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x40, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x2f, 0xd0, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0x07, 0xf8, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0x01, 0xfd, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x7f, 0x40, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x1f, 0x80, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x07, 0x90, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0x02, 0x90, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0x01, 0x40, 0xe9, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xbf, 0x01, - 0x00, 0xc0, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x01, 0x00, 0xfc, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x5b, 0xc0, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, }; - -#define GLYPH_badge_checkmark_blue_WIDTH 50 + 0xff, 0xff, 0xff, 0xff, 0xbf, 0x05, 0x00, 0xe5, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0x1f, 0x00, 0x00, 0x00, 0x40, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x1b, 0x00, 0x00, 0x00, + 0x00, 0x40, 0xfe, 0xff, 0xff, 0xff, 0xff, 0xff, 0x1f, 0x00, 0x94, 0xfe, 0x6b, 0x01, 0x40, 0xff, + 0xff, 0xff, 0xff, 0xff, 0x2f, 0x00, 0xf9, 0xff, 0xff, 0xff, 0x06, 0x80, 0xff, 0xff, 0xff, 0xff, + 0x7f, 0x00, 0xf9, 0xff, 0xff, 0xff, 0xff, 0x06, 0xd0, 0xff, 0xff, 0xff, 0xff, 0x01, 0xf8, 0xff, + 0xff, 0xff, 0xff, 0xff, 0x02, 0xf4, 0xff, 0xff, 0xff, 0x07, 0xf4, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0x01, 0xfd, 0xff, 0xff, 0x1f, 0xd0, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x7f, 0x40, 0xff, + 0xff, 0x7f, 0x80, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x2f, 0xd0, 0xff, 0xff, 0x02, 0xfd, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x07, 0xf8, 0xff, 0x0f, 0xf4, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0x01, 0xff, 0x7f, 0xc0, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0x3f, 0xd0, 0xff, 0x02, 0xfe, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x0b, 0xf8, 0x1f, + 0xf4, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x41, 0xff, 0x80, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x2f, 0xe0, 0x07, 0xfd, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0x07, 0x3d, 0xe0, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xbf, + 0xc0, 0x03, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x0f, 0x28, 0xf4, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x81, 0x41, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0x1f, 0x14, 0xf8, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0x42, 0x80, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x2f, 0x00, + 0xfc, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x03, 0xc0, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x3f, 0x00, 0xfc, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xc0, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0x0f, 0xf8, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x81, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x1f, 0xf4, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x42, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0x3f, 0xf0, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0x03, 0xfe, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x7f, 0xd0, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x0b, 0xf8, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x41, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0x2f, 0xe0, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x07, + 0xfc, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x40, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x2f, 0xd0, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0x07, 0xf8, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0x01, 0xfd, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x7f, 0x40, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x1f, 0x80, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x07, 0x90, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0x02, 0x90, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0x01, 0x40, 0xe9, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xbf, 0x01, + 0x00, 0xc0, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x01, 0x00, 0xfc, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x5b, 0xc0, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, +}; + +#define GLYPH_badge_checkmark_blue_WIDTH 50 #define GLYPH_badge_checkmark_blue_HEIGHT 50 -#define GLYPH_badge_checkmark_blue_BPP 2 +#define GLYPH_badge_checkmark_blue_BPP 2 unsigned int const C_badge_checkmark_blue_colors[] = { - 0x00cccccc, - 0x00dedede, - 0x00eeeeee, - 0x00f9f9f9, + 0x00cccccc, + 0x00dedede, + 0x00eeeeee, + 0x00f9f9f9, }; unsigned char const C_badge_checkmark_blue_bitmap[] = { - 0xff, 0xff, 0xff, 0xff, 0xaf, 0x05, 0x00, 0xe5, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0x5f, 0x00, 0x00, 0x00, 0x40, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x1b, 0x00, 0x00, 0x00, - 0x00, 0x40, 0xfe, 0xff, 0xff, 0xff, 0xff, 0xff, 0x1f, 0x00, 0x94, 0xfe, 0x6b, 0x01, 0x40, 0xff, - 0xff, 0xff, 0xff, 0xff, 0x2f, 0x00, 0xf9, 0xff, 0xff, 0xff, 0x06, 0x80, 0xff, 0xff, 0xff, 0xff, - 0x7f, 0x00, 0xf9, 0xff, 0xff, 0xff, 0xff, 0x06, 0xd0, 0xff, 0xff, 0xff, 0xff, 0x01, 0xf8, 0xff, - 0xff, 0xff, 0xff, 0xff, 0x02, 0xf4, 0xff, 0xff, 0xff, 0x07, 0xf4, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0x01, 0xfd, 0xff, 0xff, 0x1f, 0xd0, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x7f, 0x40, 0xff, - 0xff, 0x7f, 0x40, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x1f, 0xd0, 0xff, 0xff, 0x02, 0xfd, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x07, 0xf8, 0xff, 0x0f, 0xf4, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0x01, 0xff, 0x7f, 0xc0, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0x3f, 0xd0, 0xff, 0x02, 0xfe, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x0b, 0xf8, 0x1f, - 0xf4, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x41, 0xff, 0x80, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x2f, 0xf0, 0x07, 0xfd, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xeb, 0xff, 0xff, 0x07, 0x3d, 0xe0, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x2f, 0xf8, 0xff, 0xbf, - 0xc0, 0x02, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xbf, 0x00, 0xfe, 0xff, 0x0f, 0x28, 0xf4, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0x02, 0xe0, 0xff, 0xff, 0x81, 0x41, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0x07, 0x80, 0xff, 0xff, 0x1f, 0x14, 0xf8, 0xff, 0xff, 0xff, 0xff, 0xff, 0x1f, 0x00, 0xfe, - 0xff, 0xff, 0x42, 0x80, 0xff, 0xff, 0xff, 0xff, 0xff, 0x7f, 0x00, 0xf8, 0xff, 0xff, 0x2f, 0x00, - 0xfc, 0xff, 0xff, 0xff, 0xff, 0xff, 0x01, 0xe0, 0xff, 0xff, 0xff, 0x03, 0xc0, 0xff, 0xff, 0xff, - 0xfe, 0xff, 0x07, 0x80, 0xff, 0xff, 0xff, 0x3f, 0x00, 0xfc, 0xff, 0xff, 0x83, 0xff, 0x1f, 0x00, - 0xfe, 0xff, 0xff, 0xff, 0x03, 0xc0, 0xff, 0xff, 0x0f, 0xe0, 0x7f, 0x00, 0xf8, 0xff, 0xff, 0xff, - 0x3f, 0x00, 0xf8, 0xff, 0x7f, 0x00, 0xf8, 0x01, 0xe0, 0xff, 0xff, 0xff, 0xff, 0x02, 0x81, 0xff, - 0xff, 0x1f, 0x00, 0x06, 0x80, 0xff, 0xff, 0xff, 0xff, 0x2f, 0x14, 0xf4, 0xff, 0xff, 0x07, 0x00, - 0x00, 0xfe, 0xff, 0xff, 0xff, 0xff, 0x41, 0x42, 0xff, 0xff, 0xff, 0x01, 0x00, 0xf8, 0xff, 0xff, - 0xff, 0xff, 0x1f, 0x28, 0xf0, 0xff, 0xff, 0x7f, 0x00, 0xe0, 0xff, 0xff, 0xff, 0xff, 0xff, 0x80, - 0x03, 0xfe, 0xff, 0xff, 0x1f, 0x80, 0xff, 0xff, 0xff, 0xff, 0xff, 0x0b, 0x7c, 0xd0, 0xff, 0xff, - 0xff, 0x07, 0xfe, 0xff, 0xff, 0xff, 0xff, 0x7f, 0xd0, 0x0f, 0xf8, 0xff, 0xff, 0xff, 0xfa, 0xff, - 0xff, 0xff, 0xff, 0xff, 0x02, 0xff, 0x41, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0x1f, 0xf4, 0x2f, 0xe0, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xbf, 0x80, 0xff, 0x07, - 0xfc, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x03, 0xfd, 0xff, 0x40, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0x1f, 0xf0, 0xff, 0x2f, 0xd0, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0x7f, 0x80, 0xff, 0xff, 0x07, 0xf4, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x01, 0xfd, - 0xff, 0xff, 0x01, 0xfd, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x07, 0xf4, 0xff, 0xff, 0x7f, 0x40, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x1f, 0xd0, 0xff, 0xff, 0xff, 0x1f, 0x80, 0xff, 0xff, 0xff, - 0xff, 0xff, 0x2f, 0x40, 0xff, 0xff, 0xff, 0xff, 0x07, 0x90, 0xff, 0xff, 0xff, 0xff, 0x6f, 0x00, - 0xfd, 0xff, 0xff, 0xff, 0xff, 0x02, 0x90, 0xff, 0xff, 0xff, 0x6f, 0x00, 0xf8, 0xff, 0xff, 0xff, - 0xff, 0xff, 0x01, 0x40, 0xe9, 0xbf, 0x16, 0x00, 0xf4, 0xff, 0xff, 0xff, 0xff, 0xff, 0xbf, 0x01, - 0x00, 0x00, 0x00, 0x00, 0xe4, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x01, 0x00, 0x00, 0x00, - 0xf4, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x5a, 0x00, 0x50, 0xfa, 0xff, 0xff, 0xff, - 0xff, }; - - -#define GLYPH_badge_wrench_WIDTH 50 + 0xff, 0xff, 0xff, 0xff, 0xaf, 0x05, 0x00, 0xe5, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0x5f, 0x00, 0x00, 0x00, 0x40, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x1b, 0x00, 0x00, 0x00, + 0x00, 0x40, 0xfe, 0xff, 0xff, 0xff, 0xff, 0xff, 0x1f, 0x00, 0x94, 0xfe, 0x6b, 0x01, 0x40, 0xff, + 0xff, 0xff, 0xff, 0xff, 0x2f, 0x00, 0xf9, 0xff, 0xff, 0xff, 0x06, 0x80, 0xff, 0xff, 0xff, 0xff, + 0x7f, 0x00, 0xf9, 0xff, 0xff, 0xff, 0xff, 0x06, 0xd0, 0xff, 0xff, 0xff, 0xff, 0x01, 0xf8, 0xff, + 0xff, 0xff, 0xff, 0xff, 0x02, 0xf4, 0xff, 0xff, 0xff, 0x07, 0xf4, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0x01, 0xfd, 0xff, 0xff, 0x1f, 0xd0, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x7f, 0x40, 0xff, + 0xff, 0x7f, 0x40, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x1f, 0xd0, 0xff, 0xff, 0x02, 0xfd, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x07, 0xf8, 0xff, 0x0f, 0xf4, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0x01, 0xff, 0x7f, 0xc0, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0x3f, 0xd0, 0xff, 0x02, 0xfe, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x0b, 0xf8, 0x1f, + 0xf4, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x41, 0xff, 0x80, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x2f, 0xf0, 0x07, 0xfd, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xeb, 0xff, 0xff, 0x07, 0x3d, 0xe0, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x2f, 0xf8, 0xff, 0xbf, + 0xc0, 0x02, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xbf, 0x00, 0xfe, 0xff, 0x0f, 0x28, 0xf4, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0x02, 0xe0, 0xff, 0xff, 0x81, 0x41, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0x07, 0x80, 0xff, 0xff, 0x1f, 0x14, 0xf8, 0xff, 0xff, 0xff, 0xff, 0xff, 0x1f, 0x00, 0xfe, + 0xff, 0xff, 0x42, 0x80, 0xff, 0xff, 0xff, 0xff, 0xff, 0x7f, 0x00, 0xf8, 0xff, 0xff, 0x2f, 0x00, + 0xfc, 0xff, 0xff, 0xff, 0xff, 0xff, 0x01, 0xe0, 0xff, 0xff, 0xff, 0x03, 0xc0, 0xff, 0xff, 0xff, + 0xfe, 0xff, 0x07, 0x80, 0xff, 0xff, 0xff, 0x3f, 0x00, 0xfc, 0xff, 0xff, 0x83, 0xff, 0x1f, 0x00, + 0xfe, 0xff, 0xff, 0xff, 0x03, 0xc0, 0xff, 0xff, 0x0f, 0xe0, 0x7f, 0x00, 0xf8, 0xff, 0xff, 0xff, + 0x3f, 0x00, 0xf8, 0xff, 0x7f, 0x00, 0xf8, 0x01, 0xe0, 0xff, 0xff, 0xff, 0xff, 0x02, 0x81, 0xff, + 0xff, 0x1f, 0x00, 0x06, 0x80, 0xff, 0xff, 0xff, 0xff, 0x2f, 0x14, 0xf4, 0xff, 0xff, 0x07, 0x00, + 0x00, 0xfe, 0xff, 0xff, 0xff, 0xff, 0x41, 0x42, 0xff, 0xff, 0xff, 0x01, 0x00, 0xf8, 0xff, 0xff, + 0xff, 0xff, 0x1f, 0x28, 0xf0, 0xff, 0xff, 0x7f, 0x00, 0xe0, 0xff, 0xff, 0xff, 0xff, 0xff, 0x80, + 0x03, 0xfe, 0xff, 0xff, 0x1f, 0x80, 0xff, 0xff, 0xff, 0xff, 0xff, 0x0b, 0x7c, 0xd0, 0xff, 0xff, + 0xff, 0x07, 0xfe, 0xff, 0xff, 0xff, 0xff, 0x7f, 0xd0, 0x0f, 0xf8, 0xff, 0xff, 0xff, 0xfa, 0xff, + 0xff, 0xff, 0xff, 0xff, 0x02, 0xff, 0x41, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0x1f, 0xf4, 0x2f, 0xe0, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xbf, 0x80, 0xff, 0x07, + 0xfc, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x03, 0xfd, 0xff, 0x40, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0x1f, 0xf0, 0xff, 0x2f, 0xd0, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0x7f, 0x80, 0xff, 0xff, 0x07, 0xf4, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x01, 0xfd, + 0xff, 0xff, 0x01, 0xfd, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x07, 0xf4, 0xff, 0xff, 0x7f, 0x40, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x1f, 0xd0, 0xff, 0xff, 0xff, 0x1f, 0x80, 0xff, 0xff, 0xff, + 0xff, 0xff, 0x2f, 0x40, 0xff, 0xff, 0xff, 0xff, 0x07, 0x90, 0xff, 0xff, 0xff, 0xff, 0x6f, 0x00, + 0xfd, 0xff, 0xff, 0xff, 0xff, 0x02, 0x90, 0xff, 0xff, 0xff, 0x6f, 0x00, 0xf8, 0xff, 0xff, 0xff, + 0xff, 0xff, 0x01, 0x40, 0xe9, 0xbf, 0x16, 0x00, 0xf4, 0xff, 0xff, 0xff, 0xff, 0xff, 0xbf, 0x01, + 0x00, 0x00, 0x00, 0x00, 0xe4, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x01, 0x00, 0x00, 0x00, + 0xf4, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x5a, 0x00, 0x50, 0xfa, 0xff, 0xff, 0xff, + 0xff, +}; + +#define GLYPH_badge_wrench_WIDTH 50 #define GLYPH_badge_wrench_HEIGHT 50 -#define GLYPH_badge_wrench_BPP 2 +#define GLYPH_badge_wrench_BPP 2 unsigned int const C_badge_wrench_colors[] = { - 0x00cccccc, - 0x00e0e0e0, - 0x00f0f0f0, - 0x00f9f9f9, + 0x00cccccc, + 0x00e0e0e0, + 0x00f0f0f0, + 0x00f9f9f9, }; unsigned char const C_badge_wrench_bitmap[] = { - 0xff, 0xff, 0xff, 0xff, 0xaf, 0x05, 0x00, 0xa5, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0x1b, 0x00, 0x00, 0x00, 0x40, 0xfe, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x1b, 0x00, 0x00, 0x00, - 0x00, 0x40, 0xfe, 0xff, 0xff, 0xff, 0xff, 0xff, 0x1f, 0x00, 0x94, 0xfa, 0x6b, 0x01, 0x40, 0xff, - 0xff, 0xff, 0xff, 0xff, 0x2f, 0x00, 0xf9, 0xff, 0xff, 0xff, 0x06, 0x80, 0xff, 0xff, 0xff, 0xff, - 0x7f, 0x00, 0xf9, 0xff, 0xff, 0xff, 0xff, 0x06, 0xd0, 0xff, 0xff, 0xff, 0xff, 0x01, 0xf8, 0xff, - 0xff, 0xff, 0xff, 0xff, 0x02, 0xf4, 0xff, 0xff, 0xff, 0x07, 0xf4, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0x01, 0xfd, 0xff, 0xff, 0x1f, 0xd0, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x7f, 0x40, 0xff, - 0xff, 0x7f, 0x40, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x1f, 0xd0, 0xff, 0xff, 0x02, 0xfd, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x07, 0xf8, 0xff, 0x0f, 0xf4, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0x01, 0xff, 0x7f, 0xc0, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0x3f, 0xd0, 0xff, 0x02, 0xfe, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x0b, 0xf8, 0x1f, - 0xf4, 0xff, 0xff, 0xff, 0xff, 0x7f, 0x00, 0xfd, 0xff, 0xff, 0x41, 0xbf, 0x80, 0xff, 0xff, 0xff, - 0xff, 0xbf, 0x00, 0x80, 0xff, 0xff, 0x2f, 0xe0, 0x07, 0xfd, 0xff, 0xff, 0xff, 0xff, 0x03, 0x40, - 0xff, 0xff, 0xff, 0x07, 0x3d, 0xe0, 0xff, 0xff, 0xff, 0xff, 0x1f, 0x40, 0xfe, 0xff, 0xff, 0xbf, - 0xc0, 0x02, 0xff, 0xff, 0xff, 0xff, 0xff, 0x01, 0xf8, 0xff, 0xff, 0xff, 0x0f, 0x28, 0xf4, 0xff, - 0xff, 0xff, 0xff, 0x0f, 0x80, 0xff, 0xff, 0xff, 0xff, 0x81, 0x41, 0xff, 0xff, 0xff, 0xff, 0xff, - 0x00, 0xf8, 0x6f, 0xff, 0xff, 0x1f, 0x14, 0xf8, 0xff, 0xff, 0xff, 0xff, 0x1f, 0x00, 0x6d, 0xf0, - 0xff, 0xff, 0x42, 0x80, 0xff, 0xff, 0xff, 0xff, 0xbf, 0x01, 0x00, 0x40, 0xff, 0xff, 0x2f, 0x00, - 0xfc, 0xff, 0xff, 0xff, 0xff, 0x22, 0x00, 0x00, 0xfc, 0xff, 0xff, 0x03, 0xc0, 0xff, 0xff, 0xff, - 0xff, 0x0b, 0x08, 0x00, 0xe0, 0xff, 0xff, 0x3f, 0x00, 0xfc, 0xff, 0xff, 0xff, 0x2f, 0x00, 0x16, - 0xe4, 0xff, 0xff, 0xff, 0x03, 0xc0, 0xff, 0xff, 0xff, 0xbf, 0x00, 0x80, 0xff, 0xff, 0xff, 0xff, - 0x3f, 0x00, 0xf8, 0xff, 0xff, 0xff, 0x02, 0x00, 0xfe, 0xff, 0xff, 0xff, 0xff, 0x02, 0x81, 0xff, - 0xff, 0xff, 0x0b, 0x00, 0xf8, 0xff, 0xff, 0xff, 0xff, 0x2f, 0x14, 0xf4, 0xff, 0xff, 0x2f, 0x00, - 0xe0, 0xff, 0xff, 0xff, 0xff, 0xff, 0x41, 0x42, 0xff, 0xff, 0xbf, 0x00, 0x80, 0xff, 0xff, 0xff, - 0xff, 0xff, 0x1f, 0x28, 0xf0, 0xff, 0xff, 0x42, 0x01, 0xfe, 0xff, 0xff, 0xff, 0xff, 0xff, 0x80, - 0x03, 0xfe, 0xff, 0x0f, 0x14, 0xf8, 0xff, 0xff, 0xff, 0xff, 0xff, 0x0b, 0x7c, 0xd0, 0xff, 0xff, - 0x00, 0xe0, 0xff, 0xff, 0xff, 0xff, 0xff, 0x7f, 0xd0, 0x0b, 0xf8, 0xff, 0x2f, 0x80, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0x02, 0xfe, 0x41, 0xff, 0xff, 0x0b, 0xfe, 0xff, 0xff, 0xff, 0xff, 0xff, - 0x1f, 0xf4, 0x2f, 0xe0, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xbf, 0x80, 0xff, 0x07, - 0xfc, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x03, 0xfd, 0xff, 0x40, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0x1f, 0xf0, 0xff, 0x2f, 0xd0, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0x7f, 0x80, 0xff, 0xff, 0x07, 0xf4, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x01, 0xfd, - 0xff, 0xff, 0x01, 0xfd, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x07, 0xf4, 0xff, 0xff, 0x7f, 0x40, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x1f, 0xd0, 0xff, 0xff, 0xff, 0x1f, 0x80, 0xff, 0xff, 0xff, - 0xff, 0xff, 0x2f, 0x40, 0xff, 0xff, 0xff, 0xff, 0x07, 0x90, 0xff, 0xff, 0xff, 0xff, 0x6f, 0x00, - 0xfd, 0xff, 0xff, 0xff, 0xff, 0x02, 0x90, 0xff, 0xff, 0xff, 0x6f, 0x00, 0xf8, 0xff, 0xff, 0xff, - 0xff, 0xff, 0x01, 0x40, 0xe9, 0xbf, 0x16, 0x00, 0xf4, 0xff, 0xff, 0xff, 0xff, 0xff, 0xbf, 0x01, - 0x00, 0x00, 0x00, 0x00, 0xe4, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xbf, 0x01, 0x00, 0x00, 0x00, - 0xe4, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x5a, 0x00, 0x50, 0xfa, 0xff, 0xff, 0xff, - 0xff, }; - -#define GLYPH_badge_power_WIDTH 50 + 0xff, 0xff, 0xff, 0xff, 0xaf, 0x05, 0x00, 0xa5, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0x1b, 0x00, 0x00, 0x00, 0x40, 0xfe, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x1b, 0x00, 0x00, 0x00, + 0x00, 0x40, 0xfe, 0xff, 0xff, 0xff, 0xff, 0xff, 0x1f, 0x00, 0x94, 0xfa, 0x6b, 0x01, 0x40, 0xff, + 0xff, 0xff, 0xff, 0xff, 0x2f, 0x00, 0xf9, 0xff, 0xff, 0xff, 0x06, 0x80, 0xff, 0xff, 0xff, 0xff, + 0x7f, 0x00, 0xf9, 0xff, 0xff, 0xff, 0xff, 0x06, 0xd0, 0xff, 0xff, 0xff, 0xff, 0x01, 0xf8, 0xff, + 0xff, 0xff, 0xff, 0xff, 0x02, 0xf4, 0xff, 0xff, 0xff, 0x07, 0xf4, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0x01, 0xfd, 0xff, 0xff, 0x1f, 0xd0, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x7f, 0x40, 0xff, + 0xff, 0x7f, 0x40, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x1f, 0xd0, 0xff, 0xff, 0x02, 0xfd, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x07, 0xf8, 0xff, 0x0f, 0xf4, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0x01, 0xff, 0x7f, 0xc0, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0x3f, 0xd0, 0xff, 0x02, 0xfe, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x0b, 0xf8, 0x1f, + 0xf4, 0xff, 0xff, 0xff, 0xff, 0x7f, 0x00, 0xfd, 0xff, 0xff, 0x41, 0xbf, 0x80, 0xff, 0xff, 0xff, + 0xff, 0xbf, 0x00, 0x80, 0xff, 0xff, 0x2f, 0xe0, 0x07, 0xfd, 0xff, 0xff, 0xff, 0xff, 0x03, 0x40, + 0xff, 0xff, 0xff, 0x07, 0x3d, 0xe0, 0xff, 0xff, 0xff, 0xff, 0x1f, 0x40, 0xfe, 0xff, 0xff, 0xbf, + 0xc0, 0x02, 0xff, 0xff, 0xff, 0xff, 0xff, 0x01, 0xf8, 0xff, 0xff, 0xff, 0x0f, 0x28, 0xf4, 0xff, + 0xff, 0xff, 0xff, 0x0f, 0x80, 0xff, 0xff, 0xff, 0xff, 0x81, 0x41, 0xff, 0xff, 0xff, 0xff, 0xff, + 0x00, 0xf8, 0x6f, 0xff, 0xff, 0x1f, 0x14, 0xf8, 0xff, 0xff, 0xff, 0xff, 0x1f, 0x00, 0x6d, 0xf0, + 0xff, 0xff, 0x42, 0x80, 0xff, 0xff, 0xff, 0xff, 0xbf, 0x01, 0x00, 0x40, 0xff, 0xff, 0x2f, 0x00, + 0xfc, 0xff, 0xff, 0xff, 0xff, 0x22, 0x00, 0x00, 0xfc, 0xff, 0xff, 0x03, 0xc0, 0xff, 0xff, 0xff, + 0xff, 0x0b, 0x08, 0x00, 0xe0, 0xff, 0xff, 0x3f, 0x00, 0xfc, 0xff, 0xff, 0xff, 0x2f, 0x00, 0x16, + 0xe4, 0xff, 0xff, 0xff, 0x03, 0xc0, 0xff, 0xff, 0xff, 0xbf, 0x00, 0x80, 0xff, 0xff, 0xff, 0xff, + 0x3f, 0x00, 0xf8, 0xff, 0xff, 0xff, 0x02, 0x00, 0xfe, 0xff, 0xff, 0xff, 0xff, 0x02, 0x81, 0xff, + 0xff, 0xff, 0x0b, 0x00, 0xf8, 0xff, 0xff, 0xff, 0xff, 0x2f, 0x14, 0xf4, 0xff, 0xff, 0x2f, 0x00, + 0xe0, 0xff, 0xff, 0xff, 0xff, 0xff, 0x41, 0x42, 0xff, 0xff, 0xbf, 0x00, 0x80, 0xff, 0xff, 0xff, + 0xff, 0xff, 0x1f, 0x28, 0xf0, 0xff, 0xff, 0x42, 0x01, 0xfe, 0xff, 0xff, 0xff, 0xff, 0xff, 0x80, + 0x03, 0xfe, 0xff, 0x0f, 0x14, 0xf8, 0xff, 0xff, 0xff, 0xff, 0xff, 0x0b, 0x7c, 0xd0, 0xff, 0xff, + 0x00, 0xe0, 0xff, 0xff, 0xff, 0xff, 0xff, 0x7f, 0xd0, 0x0b, 0xf8, 0xff, 0x2f, 0x80, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0x02, 0xfe, 0x41, 0xff, 0xff, 0x0b, 0xfe, 0xff, 0xff, 0xff, 0xff, 0xff, + 0x1f, 0xf4, 0x2f, 0xe0, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xbf, 0x80, 0xff, 0x07, + 0xfc, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x03, 0xfd, 0xff, 0x40, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0x1f, 0xf0, 0xff, 0x2f, 0xd0, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0x7f, 0x80, 0xff, 0xff, 0x07, 0xf4, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x01, 0xfd, + 0xff, 0xff, 0x01, 0xfd, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x07, 0xf4, 0xff, 0xff, 0x7f, 0x40, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x1f, 0xd0, 0xff, 0xff, 0xff, 0x1f, 0x80, 0xff, 0xff, 0xff, + 0xff, 0xff, 0x2f, 0x40, 0xff, 0xff, 0xff, 0xff, 0x07, 0x90, 0xff, 0xff, 0xff, 0xff, 0x6f, 0x00, + 0xfd, 0xff, 0xff, 0xff, 0xff, 0x02, 0x90, 0xff, 0xff, 0xff, 0x6f, 0x00, 0xf8, 0xff, 0xff, 0xff, + 0xff, 0xff, 0x01, 0x40, 0xe9, 0xbf, 0x16, 0x00, 0xf4, 0xff, 0xff, 0xff, 0xff, 0xff, 0xbf, 0x01, + 0x00, 0x00, 0x00, 0x00, 0xe4, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xbf, 0x01, 0x00, 0x00, 0x00, + 0xe4, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x5a, 0x00, 0x50, 0xfa, 0xff, 0xff, 0xff, + 0xff, +}; + +#define GLYPH_badge_power_WIDTH 50 #define GLYPH_badge_power_HEIGHT 50 -#define GLYPH_badge_power_BPP 2 +#define GLYPH_badge_power_BPP 2 unsigned int const C_badge_power_colors[] = { - 0x00cccccc, - 0x00dddddd, - 0x00eeeeee, - 0x00f9f9f9, + 0x00cccccc, + 0x00dddddd, + 0x00eeeeee, + 0x00f9f9f9, }; unsigned char const C_badge_power_bitmap[] = { - 0xff, 0xff, 0xff, 0xff, 0xaf, 0x05, 0x00, 0xe5, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0x5f, 0x00, 0x00, 0x00, 0x40, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x1b, 0x00, 0x00, 0x00, - 0x00, 0x40, 0xfe, 0xff, 0xff, 0xff, 0xff, 0xff, 0x1f, 0x00, 0x94, 0xfe, 0x6b, 0x01, 0x40, 0xff, - 0xff, 0xff, 0xff, 0xff, 0x2f, 0x00, 0xf9, 0xff, 0xff, 0xff, 0x06, 0x80, 0xff, 0xff, 0xff, 0xff, - 0x7f, 0x00, 0xf9, 0xff, 0xff, 0xff, 0xff, 0x06, 0xd0, 0xff, 0xff, 0xff, 0xff, 0x01, 0xf8, 0xff, - 0xff, 0xff, 0xff, 0xff, 0x02, 0xf4, 0xff, 0xff, 0xff, 0x07, 0xf4, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0x01, 0xfd, 0xff, 0xff, 0x1f, 0xd0, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x7f, 0x40, 0xff, - 0xff, 0x7f, 0x80, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x2f, 0xd0, 0xff, 0xff, 0x02, 0xfd, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x07, 0xf8, 0xff, 0x0f, 0xf4, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0x01, 0xff, 0x7f, 0xc0, 0xff, 0xff, 0xff, 0xbf, 0xe0, 0xff, 0xff, 0xff, - 0x3f, 0xd0, 0xff, 0x02, 0xfe, 0xff, 0xff, 0xff, 0x07, 0xfd, 0xff, 0xff, 0xff, 0x0b, 0xf8, 0x1f, - 0xf4, 0xff, 0xff, 0xff, 0x3f, 0xc0, 0xff, 0xff, 0xff, 0xff, 0x41, 0xff, 0x80, 0xff, 0xff, 0xff, - 0xfb, 0x03, 0xfc, 0xfe, 0xff, 0xff, 0x2f, 0xf0, 0x07, 0xfd, 0xff, 0xff, 0x0b, 0x3c, 0xc0, 0x03, - 0xfe, 0xff, 0xff, 0x07, 0x3d, 0xe0, 0xff, 0xff, 0x2f, 0x80, 0x03, 0x2c, 0x80, 0xff, 0xff, 0xbf, - 0xc0, 0x02, 0xff, 0xff, 0xff, 0x00, 0x3c, 0xc0, 0x03, 0xf0, 0xff, 0xff, 0x0f, 0x28, 0xf4, 0xff, - 0xff, 0x07, 0xe0, 0x03, 0xbc, 0x00, 0xfd, 0xff, 0xff, 0x81, 0x41, 0xff, 0xff, 0x3f, 0x80, 0x3f, - 0xc0, 0x2f, 0xc0, 0xff, 0xff, 0x1f, 0x14, 0xf8, 0xff, 0xff, 0x01, 0xfd, 0x03, 0xfc, 0x07, 0xf4, - 0xff, 0xff, 0x42, 0x80, 0xff, 0xff, 0x1f, 0xf0, 0x3f, 0xc0, 0xff, 0x40, 0xff, 0xff, 0x2f, 0x00, - 0xfc, 0xff, 0xff, 0x00, 0xff, 0x07, 0xfd, 0x0f, 0xf0, 0xff, 0xff, 0x03, 0xc0, 0xff, 0xff, 0x0f, - 0xf4, 0xbf, 0xe0, 0xff, 0x01, 0xff, 0xff, 0x3f, 0x00, 0xfc, 0xff, 0xff, 0x40, 0xff, 0xff, 0xff, - 0x1f, 0xf0, 0xff, 0xff, 0x03, 0xc0, 0xff, 0xff, 0x0f, 0xf0, 0xff, 0xff, 0xff, 0x00, 0xff, 0xff, - 0x3f, 0x00, 0xf8, 0xff, 0xff, 0x01, 0xfe, 0xff, 0xff, 0x0b, 0xf4, 0xff, 0xff, 0x02, 0x81, 0xff, - 0xff, 0x2f, 0xd0, 0xff, 0xff, 0x7f, 0x80, 0xff, 0xff, 0x2f, 0x14, 0xf4, 0xff, 0xff, 0x03, 0xf8, - 0xff, 0xff, 0x02, 0xfc, 0xff, 0xff, 0x41, 0x42, 0xff, 0xff, 0x7f, 0x00, 0xfe, 0xff, 0x0b, 0xd0, - 0xff, 0xff, 0x1f, 0x28, 0xf0, 0xff, 0xff, 0x1f, 0x40, 0xfe, 0x1b, 0x40, 0xff, 0xff, 0xff, 0x80, - 0x03, 0xfe, 0xff, 0xff, 0x03, 0x00, 0x05, 0x00, 0xfc, 0xff, 0xff, 0x0b, 0x7c, 0xd0, 0xff, 0xff, - 0xff, 0x01, 0x00, 0x00, 0xf4, 0xff, 0xff, 0x7f, 0xd0, 0x0f, 0xf8, 0xff, 0xff, 0x7f, 0x00, 0x00, - 0xd0, 0xff, 0xff, 0xff, 0x02, 0xff, 0x41, 0xff, 0xff, 0xff, 0xbf, 0x01, 0xe4, 0xff, 0xff, 0xff, - 0x1f, 0xf4, 0x2f, 0xe0, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xbf, 0x80, 0xff, 0x07, - 0xfc, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x03, 0xfd, 0xff, 0x40, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0x1f, 0xf0, 0xff, 0x2f, 0xd0, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0x7f, 0x80, 0xff, 0xff, 0x07, 0xf8, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x02, 0xfd, - 0xff, 0xff, 0x01, 0xfd, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x07, 0xf4, 0xff, 0xff, 0x7f, 0x40, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x1f, 0xd0, 0xff, 0xff, 0xff, 0x1f, 0x80, 0xff, 0xff, 0xff, - 0xff, 0xff, 0x2f, 0x40, 0xff, 0xff, 0xff, 0xff, 0x07, 0x90, 0xff, 0xff, 0xff, 0xff, 0x6f, 0x00, - 0xfd, 0xff, 0xff, 0xff, 0xff, 0x02, 0x90, 0xff, 0xff, 0xff, 0x6f, 0x00, 0xf8, 0xff, 0xff, 0xff, - 0xff, 0xff, 0x01, 0x40, 0xe9, 0xbf, 0x16, 0x00, 0xf4, 0xff, 0xff, 0xff, 0xff, 0xff, 0xbf, 0x01, - 0x00, 0x00, 0x00, 0x00, 0xe4, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x01, 0x00, 0x00, 0x00, - 0xf4, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x5a, 0x00, 0x50, 0xfa, 0xff, 0xff, 0xff, - 0xff, }; - -#define GLYPH_badge_error_WIDTH 50 + 0xff, 0xff, 0xff, 0xff, 0xaf, 0x05, 0x00, 0xe5, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0x5f, 0x00, 0x00, 0x00, 0x40, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x1b, 0x00, 0x00, 0x00, + 0x00, 0x40, 0xfe, 0xff, 0xff, 0xff, 0xff, 0xff, 0x1f, 0x00, 0x94, 0xfe, 0x6b, 0x01, 0x40, 0xff, + 0xff, 0xff, 0xff, 0xff, 0x2f, 0x00, 0xf9, 0xff, 0xff, 0xff, 0x06, 0x80, 0xff, 0xff, 0xff, 0xff, + 0x7f, 0x00, 0xf9, 0xff, 0xff, 0xff, 0xff, 0x06, 0xd0, 0xff, 0xff, 0xff, 0xff, 0x01, 0xf8, 0xff, + 0xff, 0xff, 0xff, 0xff, 0x02, 0xf4, 0xff, 0xff, 0xff, 0x07, 0xf4, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0x01, 0xfd, 0xff, 0xff, 0x1f, 0xd0, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x7f, 0x40, 0xff, + 0xff, 0x7f, 0x80, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x2f, 0xd0, 0xff, 0xff, 0x02, 0xfd, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x07, 0xf8, 0xff, 0x0f, 0xf4, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0x01, 0xff, 0x7f, 0xc0, 0xff, 0xff, 0xff, 0xbf, 0xe0, 0xff, 0xff, 0xff, + 0x3f, 0xd0, 0xff, 0x02, 0xfe, 0xff, 0xff, 0xff, 0x07, 0xfd, 0xff, 0xff, 0xff, 0x0b, 0xf8, 0x1f, + 0xf4, 0xff, 0xff, 0xff, 0x3f, 0xc0, 0xff, 0xff, 0xff, 0xff, 0x41, 0xff, 0x80, 0xff, 0xff, 0xff, + 0xfb, 0x03, 0xfc, 0xfe, 0xff, 0xff, 0x2f, 0xf0, 0x07, 0xfd, 0xff, 0xff, 0x0b, 0x3c, 0xc0, 0x03, + 0xfe, 0xff, 0xff, 0x07, 0x3d, 0xe0, 0xff, 0xff, 0x2f, 0x80, 0x03, 0x2c, 0x80, 0xff, 0xff, 0xbf, + 0xc0, 0x02, 0xff, 0xff, 0xff, 0x00, 0x3c, 0xc0, 0x03, 0xf0, 0xff, 0xff, 0x0f, 0x28, 0xf4, 0xff, + 0xff, 0x07, 0xe0, 0x03, 0xbc, 0x00, 0xfd, 0xff, 0xff, 0x81, 0x41, 0xff, 0xff, 0x3f, 0x80, 0x3f, + 0xc0, 0x2f, 0xc0, 0xff, 0xff, 0x1f, 0x14, 0xf8, 0xff, 0xff, 0x01, 0xfd, 0x03, 0xfc, 0x07, 0xf4, + 0xff, 0xff, 0x42, 0x80, 0xff, 0xff, 0x1f, 0xf0, 0x3f, 0xc0, 0xff, 0x40, 0xff, 0xff, 0x2f, 0x00, + 0xfc, 0xff, 0xff, 0x00, 0xff, 0x07, 0xfd, 0x0f, 0xf0, 0xff, 0xff, 0x03, 0xc0, 0xff, 0xff, 0x0f, + 0xf4, 0xbf, 0xe0, 0xff, 0x01, 0xff, 0xff, 0x3f, 0x00, 0xfc, 0xff, 0xff, 0x40, 0xff, 0xff, 0xff, + 0x1f, 0xf0, 0xff, 0xff, 0x03, 0xc0, 0xff, 0xff, 0x0f, 0xf0, 0xff, 0xff, 0xff, 0x00, 0xff, 0xff, + 0x3f, 0x00, 0xf8, 0xff, 0xff, 0x01, 0xfe, 0xff, 0xff, 0x0b, 0xf4, 0xff, 0xff, 0x02, 0x81, 0xff, + 0xff, 0x2f, 0xd0, 0xff, 0xff, 0x7f, 0x80, 0xff, 0xff, 0x2f, 0x14, 0xf4, 0xff, 0xff, 0x03, 0xf8, + 0xff, 0xff, 0x02, 0xfc, 0xff, 0xff, 0x41, 0x42, 0xff, 0xff, 0x7f, 0x00, 0xfe, 0xff, 0x0b, 0xd0, + 0xff, 0xff, 0x1f, 0x28, 0xf0, 0xff, 0xff, 0x1f, 0x40, 0xfe, 0x1b, 0x40, 0xff, 0xff, 0xff, 0x80, + 0x03, 0xfe, 0xff, 0xff, 0x03, 0x00, 0x05, 0x00, 0xfc, 0xff, 0xff, 0x0b, 0x7c, 0xd0, 0xff, 0xff, + 0xff, 0x01, 0x00, 0x00, 0xf4, 0xff, 0xff, 0x7f, 0xd0, 0x0f, 0xf8, 0xff, 0xff, 0x7f, 0x00, 0x00, + 0xd0, 0xff, 0xff, 0xff, 0x02, 0xff, 0x41, 0xff, 0xff, 0xff, 0xbf, 0x01, 0xe4, 0xff, 0xff, 0xff, + 0x1f, 0xf4, 0x2f, 0xe0, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xbf, 0x80, 0xff, 0x07, + 0xfc, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x03, 0xfd, 0xff, 0x40, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0x1f, 0xf0, 0xff, 0x2f, 0xd0, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0x7f, 0x80, 0xff, 0xff, 0x07, 0xf8, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x02, 0xfd, + 0xff, 0xff, 0x01, 0xfd, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x07, 0xf4, 0xff, 0xff, 0x7f, 0x40, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x1f, 0xd0, 0xff, 0xff, 0xff, 0x1f, 0x80, 0xff, 0xff, 0xff, + 0xff, 0xff, 0x2f, 0x40, 0xff, 0xff, 0xff, 0xff, 0x07, 0x90, 0xff, 0xff, 0xff, 0xff, 0x6f, 0x00, + 0xfd, 0xff, 0xff, 0xff, 0xff, 0x02, 0x90, 0xff, 0xff, 0xff, 0x6f, 0x00, 0xf8, 0xff, 0xff, 0xff, + 0xff, 0xff, 0x01, 0x40, 0xe9, 0xbf, 0x16, 0x00, 0xf4, 0xff, 0xff, 0xff, 0xff, 0xff, 0xbf, 0x01, + 0x00, 0x00, 0x00, 0x00, 0xe4, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x01, 0x00, 0x00, 0x00, + 0xf4, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x5a, 0x00, 0x50, 0xfa, 0xff, 0xff, 0xff, + 0xff, +}; + +#define GLYPH_badge_error_WIDTH 50 #define GLYPH_badge_error_HEIGHT 50 -#define GLYPH_badge_error_BPP 2 +#define GLYPH_badge_error_BPP 2 unsigned int const C_badge_error_colors[] = { - 0x00ed2a45, - 0x00f28090, - 0x00f6c8ce, - 0x00f9f9f9, + 0x00ed2a45, + 0x00f28090, + 0x00f6c8ce, + 0x00f9f9f9, }; unsigned char const C_badge_error_bitmap[] = { - 0xff, 0xff, 0xff, 0xff, 0xaf, 0x05, 0x00, 0xa5, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0x1f, 0x00, 0x00, 0x00, 0x40, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x1b, 0x00, 0x00, 0x00, - 0x00, 0x40, 0xfe, 0xff, 0xff, 0xff, 0xff, 0xff, 0x1f, 0x00, 0x94, 0xfe, 0x6b, 0x01, 0x40, 0xff, - 0xff, 0xff, 0xff, 0xff, 0x2f, 0x00, 0xf9, 0xff, 0xff, 0xff, 0x06, 0x80, 0xff, 0xff, 0xff, 0xff, - 0x7f, 0x00, 0xf9, 0xff, 0xff, 0xff, 0xff, 0x06, 0xd0, 0xff, 0xff, 0xff, 0xff, 0x01, 0xf8, 0xff, - 0xff, 0xff, 0xff, 0xff, 0x02, 0xf4, 0xff, 0xff, 0xff, 0x07, 0xf4, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0x01, 0xfd, 0xff, 0xff, 0x1f, 0xd0, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x7f, 0x40, 0xff, - 0xff, 0x7f, 0x80, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x1f, 0xd0, 0xff, 0xff, 0x02, 0xfd, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x07, 0xf8, 0xff, 0x0f, 0xf4, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0x01, 0xff, 0x7f, 0xc0, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0x3f, 0xd0, 0xff, 0x02, 0xfe, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x0b, 0xf8, 0x1f, - 0xf4, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x41, 0xbf, 0x80, 0xff, 0xff, 0x5f, - 0xff, 0xff, 0xff, 0x5f, 0xff, 0xff, 0x2f, 0xf0, 0x07, 0xfd, 0xff, 0x7f, 0xd0, 0xff, 0xff, 0x7f, - 0xd0, 0xff, 0xff, 0x07, 0x3d, 0xe0, 0xff, 0xff, 0x07, 0xf4, 0xff, 0xff, 0x01, 0xfd, 0xff, 0xbf, - 0xc0, 0x02, 0xff, 0xff, 0xff, 0x01, 0xfd, 0xff, 0x07, 0xf4, 0xff, 0xff, 0x0f, 0x2c, 0xf4, 0xff, - 0xff, 0x7f, 0x40, 0xff, 0x1f, 0xd0, 0xff, 0xff, 0xff, 0x81, 0x41, 0xff, 0xff, 0xff, 0x1f, 0xd0, - 0x7f, 0x40, 0xff, 0xff, 0xff, 0x1f, 0x14, 0xf8, 0xff, 0xff, 0xff, 0x07, 0xf4, 0x01, 0xfd, 0xff, - 0xff, 0xff, 0x42, 0x80, 0xff, 0xff, 0xff, 0xff, 0x01, 0x05, 0xf4, 0xff, 0xff, 0xff, 0x2f, 0x00, - 0xfc, 0xff, 0xff, 0xff, 0x7f, 0x00, 0xd0, 0xff, 0xff, 0xff, 0xff, 0x03, 0xc0, 0xff, 0xff, 0xff, - 0xff, 0x1f, 0x40, 0xff, 0xff, 0xff, 0xff, 0x3f, 0x00, 0xfc, 0xff, 0xff, 0xff, 0xff, 0x01, 0xf4, - 0xff, 0xff, 0xff, 0xff, 0x03, 0xc0, 0xff, 0xff, 0xff, 0xff, 0x07, 0x00, 0xfd, 0xff, 0xff, 0xff, - 0x3f, 0x00, 0xf8, 0xff, 0xff, 0xff, 0x1f, 0x50, 0x40, 0xff, 0xff, 0xff, 0xff, 0x02, 0x81, 0xff, - 0xff, 0xff, 0x7f, 0x40, 0x1f, 0xd0, 0xff, 0xff, 0xff, 0x2f, 0x14, 0xf4, 0xff, 0xff, 0xff, 0x01, - 0xfd, 0x07, 0xf4, 0xff, 0xff, 0xff, 0x41, 0x42, 0xff, 0xff, 0xff, 0x07, 0xf4, 0xff, 0x01, 0xfd, - 0xff, 0xff, 0x1f, 0x28, 0xf0, 0xff, 0xff, 0x1f, 0xd0, 0xff, 0x7f, 0x40, 0xff, 0xff, 0xff, 0x80, - 0x03, 0xfe, 0xff, 0x7f, 0x40, 0xff, 0xff, 0x1f, 0xd0, 0xff, 0xff, 0x0b, 0x7c, 0xd0, 0xff, 0xff, - 0x07, 0xfd, 0xff, 0xff, 0x07, 0xfd, 0xff, 0x7f, 0xd0, 0x0b, 0xf8, 0xff, 0xff, 0xf5, 0xff, 0xff, - 0xff, 0xf5, 0xff, 0xff, 0x02, 0xfe, 0x41, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0x1f, 0xf4, 0x2f, 0xe0, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xbf, 0x80, 0xff, 0x07, - 0xfc, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x03, 0xfd, 0xff, 0x40, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0x1f, 0xf0, 0xff, 0x2f, 0xd0, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0x7f, 0x80, 0xff, 0xff, 0x07, 0xf8, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x01, 0xfd, - 0xff, 0xff, 0x01, 0xfd, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x07, 0xf4, 0xff, 0xff, 0x7f, 0x40, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x1f, 0xd0, 0xff, 0xff, 0xff, 0x1f, 0x80, 0xff, 0xff, 0xff, - 0xff, 0xff, 0x2f, 0x40, 0xff, 0xff, 0xff, 0xff, 0x07, 0x90, 0xff, 0xff, 0xff, 0xff, 0x6f, 0x00, - 0xfd, 0xff, 0xff, 0xff, 0xff, 0x02, 0x90, 0xff, 0xff, 0xff, 0x6f, 0x00, 0xf8, 0xff, 0xff, 0xff, - 0xff, 0xff, 0x01, 0x40, 0xe9, 0xbf, 0x16, 0x00, 0xf4, 0xff, 0xff, 0xff, 0xff, 0xff, 0xbf, 0x01, - 0x00, 0x00, 0x00, 0x00, 0xe4, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x01, 0x00, 0x00, 0x00, - 0xf4, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x5a, 0x00, 0x50, 0xfa, 0xff, 0xff, 0xff, - 0xff, }; - - -#define GLYPH_badge_critical_WIDTH 50 + 0xff, 0xff, 0xff, 0xff, 0xaf, 0x05, 0x00, 0xa5, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0x1f, 0x00, 0x00, 0x00, 0x40, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x1b, 0x00, 0x00, 0x00, + 0x00, 0x40, 0xfe, 0xff, 0xff, 0xff, 0xff, 0xff, 0x1f, 0x00, 0x94, 0xfe, 0x6b, 0x01, 0x40, 0xff, + 0xff, 0xff, 0xff, 0xff, 0x2f, 0x00, 0xf9, 0xff, 0xff, 0xff, 0x06, 0x80, 0xff, 0xff, 0xff, 0xff, + 0x7f, 0x00, 0xf9, 0xff, 0xff, 0xff, 0xff, 0x06, 0xd0, 0xff, 0xff, 0xff, 0xff, 0x01, 0xf8, 0xff, + 0xff, 0xff, 0xff, 0xff, 0x02, 0xf4, 0xff, 0xff, 0xff, 0x07, 0xf4, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0x01, 0xfd, 0xff, 0xff, 0x1f, 0xd0, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x7f, 0x40, 0xff, + 0xff, 0x7f, 0x80, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x1f, 0xd0, 0xff, 0xff, 0x02, 0xfd, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x07, 0xf8, 0xff, 0x0f, 0xf4, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0x01, 0xff, 0x7f, 0xc0, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0x3f, 0xd0, 0xff, 0x02, 0xfe, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x0b, 0xf8, 0x1f, + 0xf4, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x41, 0xbf, 0x80, 0xff, 0xff, 0x5f, + 0xff, 0xff, 0xff, 0x5f, 0xff, 0xff, 0x2f, 0xf0, 0x07, 0xfd, 0xff, 0x7f, 0xd0, 0xff, 0xff, 0x7f, + 0xd0, 0xff, 0xff, 0x07, 0x3d, 0xe0, 0xff, 0xff, 0x07, 0xf4, 0xff, 0xff, 0x01, 0xfd, 0xff, 0xbf, + 0xc0, 0x02, 0xff, 0xff, 0xff, 0x01, 0xfd, 0xff, 0x07, 0xf4, 0xff, 0xff, 0x0f, 0x2c, 0xf4, 0xff, + 0xff, 0x7f, 0x40, 0xff, 0x1f, 0xd0, 0xff, 0xff, 0xff, 0x81, 0x41, 0xff, 0xff, 0xff, 0x1f, 0xd0, + 0x7f, 0x40, 0xff, 0xff, 0xff, 0x1f, 0x14, 0xf8, 0xff, 0xff, 0xff, 0x07, 0xf4, 0x01, 0xfd, 0xff, + 0xff, 0xff, 0x42, 0x80, 0xff, 0xff, 0xff, 0xff, 0x01, 0x05, 0xf4, 0xff, 0xff, 0xff, 0x2f, 0x00, + 0xfc, 0xff, 0xff, 0xff, 0x7f, 0x00, 0xd0, 0xff, 0xff, 0xff, 0xff, 0x03, 0xc0, 0xff, 0xff, 0xff, + 0xff, 0x1f, 0x40, 0xff, 0xff, 0xff, 0xff, 0x3f, 0x00, 0xfc, 0xff, 0xff, 0xff, 0xff, 0x01, 0xf4, + 0xff, 0xff, 0xff, 0xff, 0x03, 0xc0, 0xff, 0xff, 0xff, 0xff, 0x07, 0x00, 0xfd, 0xff, 0xff, 0xff, + 0x3f, 0x00, 0xf8, 0xff, 0xff, 0xff, 0x1f, 0x50, 0x40, 0xff, 0xff, 0xff, 0xff, 0x02, 0x81, 0xff, + 0xff, 0xff, 0x7f, 0x40, 0x1f, 0xd0, 0xff, 0xff, 0xff, 0x2f, 0x14, 0xf4, 0xff, 0xff, 0xff, 0x01, + 0xfd, 0x07, 0xf4, 0xff, 0xff, 0xff, 0x41, 0x42, 0xff, 0xff, 0xff, 0x07, 0xf4, 0xff, 0x01, 0xfd, + 0xff, 0xff, 0x1f, 0x28, 0xf0, 0xff, 0xff, 0x1f, 0xd0, 0xff, 0x7f, 0x40, 0xff, 0xff, 0xff, 0x80, + 0x03, 0xfe, 0xff, 0x7f, 0x40, 0xff, 0xff, 0x1f, 0xd0, 0xff, 0xff, 0x0b, 0x7c, 0xd0, 0xff, 0xff, + 0x07, 0xfd, 0xff, 0xff, 0x07, 0xfd, 0xff, 0x7f, 0xd0, 0x0b, 0xf8, 0xff, 0xff, 0xf5, 0xff, 0xff, + 0xff, 0xf5, 0xff, 0xff, 0x02, 0xfe, 0x41, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0x1f, 0xf4, 0x2f, 0xe0, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xbf, 0x80, 0xff, 0x07, + 0xfc, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x03, 0xfd, 0xff, 0x40, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0x1f, 0xf0, 0xff, 0x2f, 0xd0, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0x7f, 0x80, 0xff, 0xff, 0x07, 0xf8, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x01, 0xfd, + 0xff, 0xff, 0x01, 0xfd, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x07, 0xf4, 0xff, 0xff, 0x7f, 0x40, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x1f, 0xd0, 0xff, 0xff, 0xff, 0x1f, 0x80, 0xff, 0xff, 0xff, + 0xff, 0xff, 0x2f, 0x40, 0xff, 0xff, 0xff, 0xff, 0x07, 0x90, 0xff, 0xff, 0xff, 0xff, 0x6f, 0x00, + 0xfd, 0xff, 0xff, 0xff, 0xff, 0x02, 0x90, 0xff, 0xff, 0xff, 0x6f, 0x00, 0xf8, 0xff, 0xff, 0xff, + 0xff, 0xff, 0x01, 0x40, 0xe9, 0xbf, 0x16, 0x00, 0xf4, 0xff, 0xff, 0xff, 0xff, 0xff, 0xbf, 0x01, + 0x00, 0x00, 0x00, 0x00, 0xe4, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x01, 0x00, 0x00, 0x00, + 0xf4, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x5a, 0x00, 0x50, 0xfa, 0xff, 0xff, 0xff, + 0xff, +}; + +#define GLYPH_badge_critical_WIDTH 50 #define GLYPH_badge_critical_HEIGHT 50 -#define GLYPH_badge_critical_BPP 2 +#define GLYPH_badge_critical_BPP 2 unsigned int const C_badge_critical_colors[] = { - 0x00ed2a45, - 0x00f16c7e, - 0x00f5b0b9, - 0x00f9f9f9, + 0x00ed2a45, + 0x00f16c7e, + 0x00f5b0b9, + 0x00f9f9f9, }; unsigned char const C_badge_critical_bitmap[] = { - 0xff, 0xff, 0xff, 0xff, 0xbf, 0x05, 0x00, 0xe5, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0x6f, 0x00, 0x00, 0x00, 0x90, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x1f, 0x00, 0x00, 0x00, - 0x00, 0x40, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x1f, 0x00, 0xa4, 0xff, 0xaf, 0x01, 0x40, 0xff, - 0xff, 0xff, 0xff, 0xff, 0x2f, 0x00, 0xf9, 0xff, 0xff, 0xff, 0x06, 0x80, 0xff, 0xff, 0xff, 0xff, - 0x7f, 0x00, 0xfd, 0xff, 0xff, 0xff, 0xff, 0x06, 0xd0, 0xff, 0xff, 0xff, 0xff, 0x01, 0xf8, 0xff, - 0xff, 0xff, 0xff, 0xff, 0x02, 0xf4, 0xff, 0xff, 0xff, 0x07, 0xf4, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0x01, 0xfd, 0xff, 0xff, 0x1f, 0xe0, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xbf, 0x40, 0xff, - 0xff, 0x7f, 0x80, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x2f, 0xd0, 0xff, 0xff, 0x02, 0xfe, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x0b, 0xf8, 0xff, 0x0f, 0xf4, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0x01, 0xff, 0x7f, 0xc0, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0x3f, 0xd0, 0xff, 0x02, 0xfe, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x0b, 0xfc, 0x1f, - 0xf4, 0xff, 0xff, 0xff, 0x3f, 0xc0, 0xff, 0xff, 0xff, 0xff, 0x41, 0xff, 0xc0, 0xff, 0xff, 0xff, - 0xff, 0x03, 0xfc, 0xff, 0xff, 0xff, 0x2f, 0xf0, 0x0b, 0xfd, 0xff, 0xff, 0xff, 0x3f, 0xc0, 0xff, - 0xff, 0xff, 0xff, 0x07, 0x7e, 0xe0, 0xff, 0xff, 0xff, 0xff, 0x03, 0xfc, 0xff, 0xff, 0xff, 0xbf, - 0xc0, 0x03, 0xff, 0xff, 0xff, 0xff, 0x3f, 0xc0, 0xff, 0xff, 0xff, 0xff, 0x0f, 0x2c, 0xf4, 0xff, - 0xff, 0xff, 0xff, 0x03, 0xfc, 0xff, 0xff, 0xff, 0xff, 0x81, 0x81, 0xff, 0xff, 0xff, 0xff, 0x3f, - 0xc0, 0xff, 0xff, 0xff, 0xff, 0x2f, 0x14, 0xf8, 0xff, 0xff, 0xff, 0xff, 0x03, 0xfc, 0xff, 0xff, - 0xff, 0xff, 0x42, 0xc1, 0xff, 0xff, 0xff, 0xff, 0x3f, 0xc0, 0xff, 0xff, 0xff, 0xff, 0x3f, 0x04, - 0xfc, 0xff, 0xff, 0xff, 0xff, 0x03, 0xfc, 0xff, 0xff, 0xff, 0xff, 0x03, 0xc0, 0xff, 0xff, 0xff, - 0xff, 0x3f, 0xc0, 0xff, 0xff, 0xff, 0xff, 0x3f, 0x00, 0xfc, 0xff, 0xff, 0xff, 0xff, 0x03, 0xfc, - 0xff, 0xff, 0xff, 0xff, 0x03, 0xc0, 0xff, 0xff, 0xff, 0xff, 0x3f, 0xc0, 0xff, 0xff, 0xff, 0xff, - 0x3f, 0x10, 0xfc, 0xff, 0xff, 0xff, 0xff, 0xab, 0xfe, 0xff, 0xff, 0xff, 0xff, 0x43, 0x81, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x2f, 0x14, 0xf8, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x42, 0x42, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0x1f, 0x38, 0xf0, 0xff, 0xff, 0xff, 0xff, 0xab, 0xfe, 0xff, 0xff, 0xff, 0xff, 0xc0, - 0x07, 0xfe, 0xff, 0xff, 0xff, 0x3f, 0xc0, 0xff, 0xff, 0xff, 0xff, 0x0b, 0xbd, 0xd0, 0xff, 0xff, - 0xff, 0xff, 0x03, 0xfc, 0xff, 0xff, 0xff, 0x7f, 0xe0, 0x0f, 0xfc, 0xff, 0xff, 0xff, 0x3f, 0xc0, - 0xff, 0xff, 0xff, 0xff, 0x03, 0xff, 0x41, 0xff, 0xff, 0xff, 0xff, 0x03, 0xfc, 0xff, 0xff, 0xff, - 0x1f, 0xf4, 0x2f, 0xe0, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xbf, 0x80, 0xff, 0x07, - 0xfc, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x03, 0xfd, 0xff, 0x40, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0x1f, 0xf0, 0xff, 0x2f, 0xe0, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0x7f, 0x80, 0xff, 0xff, 0x07, 0xf8, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x02, 0xfd, - 0xff, 0xff, 0x01, 0xfe, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x0b, 0xf4, 0xff, 0xff, 0x7f, 0x40, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x1f, 0xd0, 0xff, 0xff, 0xff, 0x1f, 0x80, 0xff, 0xff, 0xff, - 0xff, 0xff, 0x2f, 0x40, 0xff, 0xff, 0xff, 0xff, 0x07, 0xd0, 0xff, 0xff, 0xff, 0xff, 0x7f, 0x00, - 0xfd, 0xff, 0xff, 0xff, 0xff, 0x02, 0x90, 0xff, 0xff, 0xff, 0x6f, 0x00, 0xf8, 0xff, 0xff, 0xff, - 0xff, 0xff, 0x01, 0x40, 0xfa, 0xff, 0x1a, 0x00, 0xf4, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x01, - 0x00, 0x00, 0x00, 0x00, 0xf4, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x06, 0x00, 0x00, 0x00, - 0xf9, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x5b, 0x00, 0x50, 0xfe, 0xff, 0xff, 0xff, - 0xff, }; - -#define GLYPH_badge_assistance_WIDTH 50 + 0xff, 0xff, 0xff, 0xff, 0xbf, 0x05, 0x00, 0xe5, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0x6f, 0x00, 0x00, 0x00, 0x90, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x1f, 0x00, 0x00, 0x00, + 0x00, 0x40, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x1f, 0x00, 0xa4, 0xff, 0xaf, 0x01, 0x40, 0xff, + 0xff, 0xff, 0xff, 0xff, 0x2f, 0x00, 0xf9, 0xff, 0xff, 0xff, 0x06, 0x80, 0xff, 0xff, 0xff, 0xff, + 0x7f, 0x00, 0xfd, 0xff, 0xff, 0xff, 0xff, 0x06, 0xd0, 0xff, 0xff, 0xff, 0xff, 0x01, 0xf8, 0xff, + 0xff, 0xff, 0xff, 0xff, 0x02, 0xf4, 0xff, 0xff, 0xff, 0x07, 0xf4, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0x01, 0xfd, 0xff, 0xff, 0x1f, 0xe0, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xbf, 0x40, 0xff, + 0xff, 0x7f, 0x80, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x2f, 0xd0, 0xff, 0xff, 0x02, 0xfe, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x0b, 0xf8, 0xff, 0x0f, 0xf4, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0x01, 0xff, 0x7f, 0xc0, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0x3f, 0xd0, 0xff, 0x02, 0xfe, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x0b, 0xfc, 0x1f, + 0xf4, 0xff, 0xff, 0xff, 0x3f, 0xc0, 0xff, 0xff, 0xff, 0xff, 0x41, 0xff, 0xc0, 0xff, 0xff, 0xff, + 0xff, 0x03, 0xfc, 0xff, 0xff, 0xff, 0x2f, 0xf0, 0x0b, 0xfd, 0xff, 0xff, 0xff, 0x3f, 0xc0, 0xff, + 0xff, 0xff, 0xff, 0x07, 0x7e, 0xe0, 0xff, 0xff, 0xff, 0xff, 0x03, 0xfc, 0xff, 0xff, 0xff, 0xbf, + 0xc0, 0x03, 0xff, 0xff, 0xff, 0xff, 0x3f, 0xc0, 0xff, 0xff, 0xff, 0xff, 0x0f, 0x2c, 0xf4, 0xff, + 0xff, 0xff, 0xff, 0x03, 0xfc, 0xff, 0xff, 0xff, 0xff, 0x81, 0x81, 0xff, 0xff, 0xff, 0xff, 0x3f, + 0xc0, 0xff, 0xff, 0xff, 0xff, 0x2f, 0x14, 0xf8, 0xff, 0xff, 0xff, 0xff, 0x03, 0xfc, 0xff, 0xff, + 0xff, 0xff, 0x42, 0xc1, 0xff, 0xff, 0xff, 0xff, 0x3f, 0xc0, 0xff, 0xff, 0xff, 0xff, 0x3f, 0x04, + 0xfc, 0xff, 0xff, 0xff, 0xff, 0x03, 0xfc, 0xff, 0xff, 0xff, 0xff, 0x03, 0xc0, 0xff, 0xff, 0xff, + 0xff, 0x3f, 0xc0, 0xff, 0xff, 0xff, 0xff, 0x3f, 0x00, 0xfc, 0xff, 0xff, 0xff, 0xff, 0x03, 0xfc, + 0xff, 0xff, 0xff, 0xff, 0x03, 0xc0, 0xff, 0xff, 0xff, 0xff, 0x3f, 0xc0, 0xff, 0xff, 0xff, 0xff, + 0x3f, 0x10, 0xfc, 0xff, 0xff, 0xff, 0xff, 0xab, 0xfe, 0xff, 0xff, 0xff, 0xff, 0x43, 0x81, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x2f, 0x14, 0xf8, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x42, 0x42, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0x1f, 0x38, 0xf0, 0xff, 0xff, 0xff, 0xff, 0xab, 0xfe, 0xff, 0xff, 0xff, 0xff, 0xc0, + 0x07, 0xfe, 0xff, 0xff, 0xff, 0x3f, 0xc0, 0xff, 0xff, 0xff, 0xff, 0x0b, 0xbd, 0xd0, 0xff, 0xff, + 0xff, 0xff, 0x03, 0xfc, 0xff, 0xff, 0xff, 0x7f, 0xe0, 0x0f, 0xfc, 0xff, 0xff, 0xff, 0x3f, 0xc0, + 0xff, 0xff, 0xff, 0xff, 0x03, 0xff, 0x41, 0xff, 0xff, 0xff, 0xff, 0x03, 0xfc, 0xff, 0xff, 0xff, + 0x1f, 0xf4, 0x2f, 0xe0, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xbf, 0x80, 0xff, 0x07, + 0xfc, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x03, 0xfd, 0xff, 0x40, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0x1f, 0xf0, 0xff, 0x2f, 0xe0, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0x7f, 0x80, 0xff, 0xff, 0x07, 0xf8, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x02, 0xfd, + 0xff, 0xff, 0x01, 0xfe, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x0b, 0xf4, 0xff, 0xff, 0x7f, 0x40, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x1f, 0xd0, 0xff, 0xff, 0xff, 0x1f, 0x80, 0xff, 0xff, 0xff, + 0xff, 0xff, 0x2f, 0x40, 0xff, 0xff, 0xff, 0xff, 0x07, 0xd0, 0xff, 0xff, 0xff, 0xff, 0x7f, 0x00, + 0xfd, 0xff, 0xff, 0xff, 0xff, 0x02, 0x90, 0xff, 0xff, 0xff, 0x6f, 0x00, 0xf8, 0xff, 0xff, 0xff, + 0xff, 0xff, 0x01, 0x40, 0xfa, 0xff, 0x1a, 0x00, 0xf4, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x01, + 0x00, 0x00, 0x00, 0x00, 0xf4, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x06, 0x00, 0x00, 0x00, + 0xf9, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x5b, 0x00, 0x50, 0xfe, 0xff, 0xff, 0xff, + 0xff, +}; + +#define GLYPH_badge_assistance_WIDTH 50 #define GLYPH_badge_assistance_HEIGHT 50 -#define GLYPH_badge_assistance_BPP 2 +#define GLYPH_badge_assistance_BPP 2 unsigned int const C_badge_assistance_colors[] = { - 0x00cccccc, - 0x00dcdcdc, - 0x00eeeeee, - 0x00f9f9f9, + 0x00cccccc, + 0x00dcdcdc, + 0x00eeeeee, + 0x00f9f9f9, }; unsigned char const C_badge_assistance_bitmap[] = { - 0xff, 0xff, 0xff, 0xff, 0xaf, 0x05, 0x00, 0xe5, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0x5f, 0x00, 0x00, 0x00, 0x40, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x1b, 0x00, 0x00, 0x00, - 0x00, 0x40, 0xfe, 0xff, 0xff, 0xff, 0xff, 0xff, 0x1f, 0x00, 0x94, 0xfe, 0x6b, 0x01, 0x40, 0xff, - 0xff, 0xff, 0xff, 0xff, 0x2f, 0x00, 0xf9, 0xff, 0xff, 0xff, 0x06, 0x80, 0xff, 0xff, 0xff, 0xff, - 0x7f, 0x00, 0xf9, 0xff, 0xff, 0xff, 0xff, 0x06, 0xd0, 0xff, 0xff, 0xff, 0xff, 0x01, 0xf8, 0xff, - 0xff, 0xff, 0xff, 0xff, 0x02, 0xf4, 0xff, 0xff, 0xff, 0x07, 0xf4, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0x01, 0xfd, 0xff, 0xff, 0x1f, 0xd0, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x7f, 0x40, 0xff, - 0xff, 0x7f, 0x80, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x2f, 0xd0, 0xff, 0xff, 0x02, 0xfd, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x07, 0xf8, 0xff, 0x0f, 0xf4, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0x01, 0xff, 0x7f, 0xc0, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0x3f, 0xd0, 0xff, 0x02, 0xfe, 0xff, 0xff, 0x7f, 0x01, 0xd4, 0xff, 0xff, 0xff, 0x0b, 0xf8, 0x1f, - 0xf4, 0xff, 0xff, 0x7f, 0x40, 0x05, 0xd0, 0xff, 0xff, 0xff, 0x41, 0xff, 0x80, 0xff, 0xff, 0xbf, - 0x90, 0xff, 0x6f, 0xe0, 0xff, 0xff, 0x2f, 0xf0, 0x07, 0xfd, 0xff, 0xff, 0x01, 0xfd, 0xff, 0x07, - 0xf4, 0xff, 0xff, 0x07, 0x7d, 0xe0, 0xff, 0xff, 0x0b, 0x40, 0xff, 0x1f, 0x00, 0xfe, 0xff, 0xbf, - 0xc0, 0x02, 0xff, 0xff, 0x3f, 0x00, 0x50, 0x55, 0x00, 0xc0, 0xff, 0xff, 0x0f, 0x28, 0xf4, 0xff, - 0xff, 0x01, 0x00, 0x00, 0x00, 0x00, 0xf4, 0xff, 0xff, 0x81, 0x41, 0xff, 0xff, 0x4b, 0x01, 0xd0, - 0x7f, 0x00, 0x14, 0xff, 0xff, 0x1f, 0x14, 0xf8, 0xff, 0x7f, 0x78, 0x80, 0xff, 0x2f, 0xd0, 0xd2, - 0xff, 0xff, 0x42, 0x80, 0xff, 0xff, 0xc7, 0x1f, 0xfd, 0xff, 0x47, 0x3f, 0xfd, 0xff, 0x2f, 0x00, - 0xfc, 0xff, 0x3f, 0xfd, 0xf1, 0xff, 0xff, 0xf4, 0xc3, 0xff, 0xff, 0x03, 0xc0, 0xff, 0xff, 0xd3, - 0x1f, 0xff, 0xff, 0x4f, 0x7f, 0xfc, 0xff, 0x3f, 0x00, 0xfc, 0xff, 0x3f, 0xfd, 0xf1, 0xff, 0xff, - 0xf4, 0xc7, 0xff, 0xff, 0x03, 0xc0, 0xff, 0xff, 0xd3, 0x1f, 0xff, 0xff, 0x4f, 0x3f, 0xfc, 0xff, - 0x3f, 0x00, 0xf8, 0xff, 0x7f, 0xfc, 0xd1, 0xff, 0x7f, 0xf4, 0xd3, 0xff, 0xff, 0x02, 0x81, 0xff, - 0xff, 0x87, 0x07, 0xf8, 0xff, 0x02, 0x2d, 0xfd, 0xff, 0x2f, 0x14, 0xf4, 0xff, 0xff, 0x14, 0x00, - 0xfd, 0x07, 0x40, 0xf1, 0xff, 0xff, 0x41, 0x42, 0xff, 0xff, 0x1f, 0x00, 0x00, 0x00, 0x00, 0x40, - 0xff, 0xff, 0x1f, 0x28, 0xf0, 0xff, 0xff, 0x03, 0x00, 0x55, 0x05, 0x00, 0xfc, 0xff, 0xff, 0x80, - 0x03, 0xfe, 0xff, 0xbf, 0x00, 0xf4, 0xff, 0x01, 0xe0, 0xff, 0xff, 0x0b, 0x7c, 0xd0, 0xff, 0xff, - 0x1f, 0xd0, 0xff, 0x7f, 0x40, 0xff, 0xff, 0x7f, 0xd0, 0x0f, 0xf8, 0xff, 0xff, 0x0b, 0xf9, 0xff, - 0x06, 0xfe, 0xff, 0xff, 0x02, 0xff, 0x41, 0xff, 0xff, 0xff, 0x07, 0x50, 0x00, 0xfd, 0xff, 0xff, - 0x1f, 0xf4, 0x2f, 0xe0, 0xff, 0xff, 0xff, 0x17, 0x40, 0xfd, 0xff, 0xff, 0xbf, 0x80, 0xff, 0x07, - 0xfc, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x03, 0xfd, 0xff, 0x40, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0x1f, 0xf0, 0xff, 0x2f, 0xd0, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0x7f, 0x80, 0xff, 0xff, 0x07, 0xf8, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x02, 0xfd, - 0xff, 0xff, 0x01, 0xfd, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x07, 0xf4, 0xff, 0xff, 0x7f, 0x40, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x1f, 0xd0, 0xff, 0xff, 0xff, 0x1f, 0x80, 0xff, 0xff, 0xff, - 0xff, 0xff, 0x2f, 0x40, 0xff, 0xff, 0xff, 0xff, 0x07, 0x90, 0xff, 0xff, 0xff, 0xff, 0x6f, 0x00, - 0xfd, 0xff, 0xff, 0xff, 0xff, 0x02, 0x90, 0xff, 0xff, 0xff, 0x6f, 0x00, 0xf8, 0xff, 0xff, 0xff, - 0xff, 0xff, 0x01, 0x40, 0xe9, 0xbf, 0x16, 0x00, 0xf4, 0xff, 0xff, 0xff, 0xff, 0xff, 0xbf, 0x01, - 0x00, 0x00, 0x00, 0x00, 0xe4, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x01, 0x00, 0x00, 0x00, - 0xf4, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x5a, 0x00, 0x50, 0xfa, 0xff, 0xff, 0xff, - 0xff, }; - - -#define GLYPH_badge_lock_blue_WIDTH 50 + 0xff, 0xff, 0xff, 0xff, 0xaf, 0x05, 0x00, 0xe5, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0x5f, 0x00, 0x00, 0x00, 0x40, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x1b, 0x00, 0x00, 0x00, + 0x00, 0x40, 0xfe, 0xff, 0xff, 0xff, 0xff, 0xff, 0x1f, 0x00, 0x94, 0xfe, 0x6b, 0x01, 0x40, 0xff, + 0xff, 0xff, 0xff, 0xff, 0x2f, 0x00, 0xf9, 0xff, 0xff, 0xff, 0x06, 0x80, 0xff, 0xff, 0xff, 0xff, + 0x7f, 0x00, 0xf9, 0xff, 0xff, 0xff, 0xff, 0x06, 0xd0, 0xff, 0xff, 0xff, 0xff, 0x01, 0xf8, 0xff, + 0xff, 0xff, 0xff, 0xff, 0x02, 0xf4, 0xff, 0xff, 0xff, 0x07, 0xf4, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0x01, 0xfd, 0xff, 0xff, 0x1f, 0xd0, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x7f, 0x40, 0xff, + 0xff, 0x7f, 0x80, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x2f, 0xd0, 0xff, 0xff, 0x02, 0xfd, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x07, 0xf8, 0xff, 0x0f, 0xf4, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0x01, 0xff, 0x7f, 0xc0, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0x3f, 0xd0, 0xff, 0x02, 0xfe, 0xff, 0xff, 0x7f, 0x01, 0xd4, 0xff, 0xff, 0xff, 0x0b, 0xf8, 0x1f, + 0xf4, 0xff, 0xff, 0x7f, 0x40, 0x05, 0xd0, 0xff, 0xff, 0xff, 0x41, 0xff, 0x80, 0xff, 0xff, 0xbf, + 0x90, 0xff, 0x6f, 0xe0, 0xff, 0xff, 0x2f, 0xf0, 0x07, 0xfd, 0xff, 0xff, 0x01, 0xfd, 0xff, 0x07, + 0xf4, 0xff, 0xff, 0x07, 0x7d, 0xe0, 0xff, 0xff, 0x0b, 0x40, 0xff, 0x1f, 0x00, 0xfe, 0xff, 0xbf, + 0xc0, 0x02, 0xff, 0xff, 0x3f, 0x00, 0x50, 0x55, 0x00, 0xc0, 0xff, 0xff, 0x0f, 0x28, 0xf4, 0xff, + 0xff, 0x01, 0x00, 0x00, 0x00, 0x00, 0xf4, 0xff, 0xff, 0x81, 0x41, 0xff, 0xff, 0x4b, 0x01, 0xd0, + 0x7f, 0x00, 0x14, 0xff, 0xff, 0x1f, 0x14, 0xf8, 0xff, 0x7f, 0x78, 0x80, 0xff, 0x2f, 0xd0, 0xd2, + 0xff, 0xff, 0x42, 0x80, 0xff, 0xff, 0xc7, 0x1f, 0xfd, 0xff, 0x47, 0x3f, 0xfd, 0xff, 0x2f, 0x00, + 0xfc, 0xff, 0x3f, 0xfd, 0xf1, 0xff, 0xff, 0xf4, 0xc3, 0xff, 0xff, 0x03, 0xc0, 0xff, 0xff, 0xd3, + 0x1f, 0xff, 0xff, 0x4f, 0x7f, 0xfc, 0xff, 0x3f, 0x00, 0xfc, 0xff, 0x3f, 0xfd, 0xf1, 0xff, 0xff, + 0xf4, 0xc7, 0xff, 0xff, 0x03, 0xc0, 0xff, 0xff, 0xd3, 0x1f, 0xff, 0xff, 0x4f, 0x3f, 0xfc, 0xff, + 0x3f, 0x00, 0xf8, 0xff, 0x7f, 0xfc, 0xd1, 0xff, 0x7f, 0xf4, 0xd3, 0xff, 0xff, 0x02, 0x81, 0xff, + 0xff, 0x87, 0x07, 0xf8, 0xff, 0x02, 0x2d, 0xfd, 0xff, 0x2f, 0x14, 0xf4, 0xff, 0xff, 0x14, 0x00, + 0xfd, 0x07, 0x40, 0xf1, 0xff, 0xff, 0x41, 0x42, 0xff, 0xff, 0x1f, 0x00, 0x00, 0x00, 0x00, 0x40, + 0xff, 0xff, 0x1f, 0x28, 0xf0, 0xff, 0xff, 0x03, 0x00, 0x55, 0x05, 0x00, 0xfc, 0xff, 0xff, 0x80, + 0x03, 0xfe, 0xff, 0xbf, 0x00, 0xf4, 0xff, 0x01, 0xe0, 0xff, 0xff, 0x0b, 0x7c, 0xd0, 0xff, 0xff, + 0x1f, 0xd0, 0xff, 0x7f, 0x40, 0xff, 0xff, 0x7f, 0xd0, 0x0f, 0xf8, 0xff, 0xff, 0x0b, 0xf9, 0xff, + 0x06, 0xfe, 0xff, 0xff, 0x02, 0xff, 0x41, 0xff, 0xff, 0xff, 0x07, 0x50, 0x00, 0xfd, 0xff, 0xff, + 0x1f, 0xf4, 0x2f, 0xe0, 0xff, 0xff, 0xff, 0x17, 0x40, 0xfd, 0xff, 0xff, 0xbf, 0x80, 0xff, 0x07, + 0xfc, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x03, 0xfd, 0xff, 0x40, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0x1f, 0xf0, 0xff, 0x2f, 0xd0, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0x7f, 0x80, 0xff, 0xff, 0x07, 0xf8, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x02, 0xfd, + 0xff, 0xff, 0x01, 0xfd, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x07, 0xf4, 0xff, 0xff, 0x7f, 0x40, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x1f, 0xd0, 0xff, 0xff, 0xff, 0x1f, 0x80, 0xff, 0xff, 0xff, + 0xff, 0xff, 0x2f, 0x40, 0xff, 0xff, 0xff, 0xff, 0x07, 0x90, 0xff, 0xff, 0xff, 0xff, 0x6f, 0x00, + 0xfd, 0xff, 0xff, 0xff, 0xff, 0x02, 0x90, 0xff, 0xff, 0xff, 0x6f, 0x00, 0xf8, 0xff, 0xff, 0xff, + 0xff, 0xff, 0x01, 0x40, 0xe9, 0xbf, 0x16, 0x00, 0xf4, 0xff, 0xff, 0xff, 0xff, 0xff, 0xbf, 0x01, + 0x00, 0x00, 0x00, 0x00, 0xe4, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x01, 0x00, 0x00, 0x00, + 0xf4, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x5a, 0x00, 0x50, 0xfa, 0xff, 0xff, 0xff, + 0xff, +}; + +#define GLYPH_badge_lock_blue_WIDTH 50 #define GLYPH_badge_lock_blue_HEIGHT 50 -#define GLYPH_badge_lock_blue_BPP 2 +#define GLYPH_badge_lock_blue_BPP 2 unsigned int const C_badge_lock_blue_colors[] = { - 0x00cccccc, - 0x00dcdcdc, - 0x00ededed, - 0x00f9f9f9, + 0x00cccccc, + 0x00dcdcdc, + 0x00ededed, + 0x00f9f9f9, }; unsigned char const C_badge_lock_blue_bitmap[] = { - 0xff, 0xff, 0xff, 0xff, 0xaf, 0x05, 0x00, 0xe5, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0x6f, 0x00, 0x00, 0x00, 0x40, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0x1b, 0x00, 0x00, 0x00, 0x00, 0x40, 0xfe, 0xff, 0xff, 0xff, 0xff, - 0xff, 0x1f, 0x00, 0x94, 0xfe, 0x6b, 0x01, 0x40, 0xff, 0xff, 0xff, 0xff, 0xff, - 0x2f, 0x00, 0xf9, 0xff, 0xff, 0xff, 0x06, 0x80, 0xff, 0xff, 0xff, 0xff, 0x7f, - 0x00, 0xf9, 0xff, 0xff, 0xff, 0xff, 0x06, 0xd0, 0xff, 0xff, 0xff, 0xff, 0x01, - 0xf8, 0xff, 0xff, 0xff, 0xff, 0xff, 0x02, 0xf4, 0xff, 0xff, 0xff, 0x07, 0xf4, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x01, 0xfd, 0xff, 0xff, 0x1f, 0xd0, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0x7f, 0x40, 0xff, 0xff, 0x7f, 0x80, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0x2f, 0xd0, 0xff, 0xff, 0x02, 0xfd, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0x07, 0xf8, 0xff, 0x0f, 0xf4, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0x01, 0xff, 0x7f, 0xc0, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0x3f, 0xd0, 0xff, 0x02, 0xfe, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0x0b, 0xf8, 0x1f, 0xf4, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0x41, 0xff, 0x80, 0xff, 0xff, 0xff, 0xff, 0x06, 0xe4, - 0xff, 0xff, 0xff, 0x2f, 0xf0, 0x07, 0xfd, 0xff, 0xff, 0xff, 0x0b, 0x00, 0xf8, - 0xff, 0xff, 0xff, 0x07, 0x7d, 0xe0, 0xff, 0xff, 0xff, 0x2f, 0x50, 0x01, 0xfe, - 0xff, 0xff, 0xbf, 0xc0, 0x02, 0xff, 0xff, 0xff, 0xff, 0x80, 0xbf, 0xc0, 0xff, - 0xff, 0xff, 0x0f, 0x28, 0xf4, 0xff, 0xff, 0xff, 0x0b, 0xfe, 0x2f, 0xf8, 0xff, - 0xff, 0xff, 0x81, 0x41, 0xff, 0xff, 0xff, 0xbf, 0xe0, 0xff, 0x82, 0xff, 0xff, - 0xff, 0x1f, 0x14, 0xf8, 0xff, 0xff, 0xff, 0x0b, 0xfe, 0x2f, 0xf8, 0xff, 0xff, - 0xff, 0x42, 0x80, 0xff, 0xff, 0xff, 0xbf, 0xe0, 0xff, 0x82, 0xff, 0xff, 0xff, - 0x2f, 0x00, 0xfc, 0xff, 0xff, 0xff, 0x01, 0x54, 0x05, 0xd0, 0xff, 0xff, 0xff, - 0x03, 0xc0, 0xff, 0xff, 0xff, 0x0f, 0x00, 0x00, 0x00, 0xfc, 0xff, 0xff, 0x3f, - 0x00, 0xfc, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0xc0, 0xff, 0xff, 0xff, 0x03, - 0xc0, 0xff, 0xff, 0xff, 0x0f, 0x00, 0x00, 0x00, 0xfc, 0xff, 0xff, 0x3f, 0x00, - 0xf8, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0xc0, 0xff, 0xff, 0xff, 0x02, 0x81, - 0xff, 0xff, 0xff, 0x0f, 0x00, 0x00, 0x00, 0xfc, 0xff, 0xff, 0x2f, 0x14, 0xf4, - 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0xc0, 0xff, 0xff, 0xff, 0x41, 0x42, 0xff, - 0xff, 0xff, 0x0f, 0x00, 0x00, 0x00, 0xfc, 0xff, 0xff, 0x1f, 0x28, 0xf0, 0xff, - 0xff, 0xff, 0x00, 0x00, 0x00, 0xc0, 0xff, 0xff, 0xff, 0x80, 0x03, 0xfe, 0xff, - 0xff, 0x1f, 0x00, 0x00, 0x00, 0xfd, 0xff, 0xff, 0x0b, 0x7c, 0xd0, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x7f, 0xd0, 0x0f, 0xf8, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x02, 0xff, 0x41, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x1f, 0xf4, 0x2f, 0xe0, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xbf, 0x80, 0xff, 0x07, 0xfc, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0x03, 0xfd, 0xff, 0x40, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0x1f, 0xf0, 0xff, 0x2f, 0xd0, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0x7f, 0x80, 0xff, 0xff, 0x07, 0xf8, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0x02, 0xfd, 0xff, 0xff, 0x01, 0xfd, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0x07, 0xf4, 0xff, 0xff, 0x7f, 0x40, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0x1f, 0xd0, 0xff, 0xff, 0xff, 0x1f, 0x80, 0xff, 0xff, 0xff, 0xff, 0xff, - 0x2f, 0x40, 0xff, 0xff, 0xff, 0xff, 0x07, 0x90, 0xff, 0xff, 0xff, 0xff, 0x6f, - 0x00, 0xfd, 0xff, 0xff, 0xff, 0xff, 0x02, 0x90, 0xff, 0xff, 0xff, 0x6f, 0x00, - 0xf8, 0xff, 0xff, 0xff, 0xff, 0xff, 0x01, 0x40, 0xe9, 0xbf, 0x16, 0x00, 0xf4, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xbf, 0x01, 0x00, 0x00, 0x00, 0x00, 0xe4, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x01, 0x00, 0x00, 0x00, 0xf4, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x5a, 0x00, 0x50, 0xfa, 0xff, 0xff, 0xff, - 0xff, }; - - -#define GLYPH_icon_checkmark_WIDTH 12 + 0xff, 0xff, 0xff, 0xff, 0xaf, 0x05, 0x00, 0xe5, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0x6f, 0x00, 0x00, 0x00, 0x40, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x1b, 0x00, 0x00, 0x00, + 0x00, 0x40, 0xfe, 0xff, 0xff, 0xff, 0xff, 0xff, 0x1f, 0x00, 0x94, 0xfe, 0x6b, 0x01, 0x40, 0xff, + 0xff, 0xff, 0xff, 0xff, 0x2f, 0x00, 0xf9, 0xff, 0xff, 0xff, 0x06, 0x80, 0xff, 0xff, 0xff, 0xff, + 0x7f, 0x00, 0xf9, 0xff, 0xff, 0xff, 0xff, 0x06, 0xd0, 0xff, 0xff, 0xff, 0xff, 0x01, 0xf8, 0xff, + 0xff, 0xff, 0xff, 0xff, 0x02, 0xf4, 0xff, 0xff, 0xff, 0x07, 0xf4, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0x01, 0xfd, 0xff, 0xff, 0x1f, 0xd0, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x7f, 0x40, 0xff, + 0xff, 0x7f, 0x80, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x2f, 0xd0, 0xff, 0xff, 0x02, 0xfd, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x07, 0xf8, 0xff, 0x0f, 0xf4, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0x01, 0xff, 0x7f, 0xc0, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0x3f, 0xd0, 0xff, 0x02, 0xfe, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x0b, 0xf8, 0x1f, + 0xf4, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x41, 0xff, 0x80, 0xff, 0xff, 0xff, + 0xff, 0x06, 0xe4, 0xff, 0xff, 0xff, 0x2f, 0xf0, 0x07, 0xfd, 0xff, 0xff, 0xff, 0x0b, 0x00, 0xf8, + 0xff, 0xff, 0xff, 0x07, 0x7d, 0xe0, 0xff, 0xff, 0xff, 0x2f, 0x50, 0x01, 0xfe, 0xff, 0xff, 0xbf, + 0xc0, 0x02, 0xff, 0xff, 0xff, 0xff, 0x80, 0xbf, 0xc0, 0xff, 0xff, 0xff, 0x0f, 0x28, 0xf4, 0xff, + 0xff, 0xff, 0x0b, 0xfe, 0x2f, 0xf8, 0xff, 0xff, 0xff, 0x81, 0x41, 0xff, 0xff, 0xff, 0xbf, 0xe0, + 0xff, 0x82, 0xff, 0xff, 0xff, 0x1f, 0x14, 0xf8, 0xff, 0xff, 0xff, 0x0b, 0xfe, 0x2f, 0xf8, 0xff, + 0xff, 0xff, 0x42, 0x80, 0xff, 0xff, 0xff, 0xbf, 0xe0, 0xff, 0x82, 0xff, 0xff, 0xff, 0x2f, 0x00, + 0xfc, 0xff, 0xff, 0xff, 0x01, 0x54, 0x05, 0xd0, 0xff, 0xff, 0xff, 0x03, 0xc0, 0xff, 0xff, 0xff, + 0x0f, 0x00, 0x00, 0x00, 0xfc, 0xff, 0xff, 0x3f, 0x00, 0xfc, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, + 0xc0, 0xff, 0xff, 0xff, 0x03, 0xc0, 0xff, 0xff, 0xff, 0x0f, 0x00, 0x00, 0x00, 0xfc, 0xff, 0xff, + 0x3f, 0x00, 0xf8, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0xc0, 0xff, 0xff, 0xff, 0x02, 0x81, 0xff, + 0xff, 0xff, 0x0f, 0x00, 0x00, 0x00, 0xfc, 0xff, 0xff, 0x2f, 0x14, 0xf4, 0xff, 0xff, 0xff, 0x00, + 0x00, 0x00, 0xc0, 0xff, 0xff, 0xff, 0x41, 0x42, 0xff, 0xff, 0xff, 0x0f, 0x00, 0x00, 0x00, 0xfc, + 0xff, 0xff, 0x1f, 0x28, 0xf0, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0xc0, 0xff, 0xff, 0xff, 0x80, + 0x03, 0xfe, 0xff, 0xff, 0x1f, 0x00, 0x00, 0x00, 0xfd, 0xff, 0xff, 0x0b, 0x7c, 0xd0, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x7f, 0xd0, 0x0f, 0xf8, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0x02, 0xff, 0x41, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0x1f, 0xf4, 0x2f, 0xe0, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xbf, 0x80, 0xff, 0x07, + 0xfc, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x03, 0xfd, 0xff, 0x40, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0x1f, 0xf0, 0xff, 0x2f, 0xd0, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0x7f, 0x80, 0xff, 0xff, 0x07, 0xf8, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x02, 0xfd, + 0xff, 0xff, 0x01, 0xfd, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x07, 0xf4, 0xff, 0xff, 0x7f, 0x40, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x1f, 0xd0, 0xff, 0xff, 0xff, 0x1f, 0x80, 0xff, 0xff, 0xff, + 0xff, 0xff, 0x2f, 0x40, 0xff, 0xff, 0xff, 0xff, 0x07, 0x90, 0xff, 0xff, 0xff, 0xff, 0x6f, 0x00, + 0xfd, 0xff, 0xff, 0xff, 0xff, 0x02, 0x90, 0xff, 0xff, 0xff, 0x6f, 0x00, 0xf8, 0xff, 0xff, 0xff, + 0xff, 0xff, 0x01, 0x40, 0xe9, 0xbf, 0x16, 0x00, 0xf4, 0xff, 0xff, 0xff, 0xff, 0xff, 0xbf, 0x01, + 0x00, 0x00, 0x00, 0x00, 0xe4, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x01, 0x00, 0x00, 0x00, + 0xf4, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x5a, 0x00, 0x50, 0xfa, 0xff, 0xff, 0xff, + 0xff, +}; + +#define GLYPH_icon_checkmark_WIDTH 12 #define GLYPH_icon_checkmark_HEIGHT 12 -#define GLYPH_icon_checkmark_BPP 2 +#define GLYPH_icon_checkmark_BPP 2 unsigned int const C_icon_checkmark_colors[] = { - 0x00cccccc, - 0x00d6d6d6, - 0x00e8e8e8, - 0x00f8f8f8, + 0x00cccccc, + 0x00d6d6d6, + 0x00e8e8e8, + 0x00f8f8f8, }; unsigned char const C_icon_checkmark_bitmap[] = { - 0xbf, 0x41, 0xfe, 0x1f, - 0x00, 0xf4, 0x07, 0x00, - 0xd0, 0x02, 0x00, 0x82, - 0x01, 0x80, 0x4b, 0x00, - 0xe0, 0x02, 0xd0, 0xb9, - 0x00, 0xd1, 0x2f, 0x40, - 0x42, 0x0b, 0x80, 0x07, - 0x01, 0xd0, 0x1f, 0x00, - 0xf4, 0xbf, 0x41, 0xfe, - }; - -#define GLYPH_app_firmware_WIDTH 50 + 0xbf, 0x41, 0xfe, 0x1f, 0x00, 0xf4, 0x07, 0x00, 0xd0, 0x02, 0x00, 0x82, + 0x01, 0x80, 0x4b, 0x00, 0xe0, 0x02, 0xd0, 0xb9, 0x00, 0xd1, 0x2f, 0x40, + 0x42, 0x0b, 0x80, 0x07, 0x01, 0xd0, 0x1f, 0x00, 0xf4, 0xbf, 0x41, 0xfe, +}; + +#define GLYPH_app_firmware_WIDTH 50 #define GLYPH_app_firmware_HEIGHT 50 -#define GLYPH_app_firmware_BPP 4 +#define GLYPH_app_firmware_BPP 4 unsigned int const C_app_firmware_colors[] = { - 0x00cccccc, - 0x00cecece, - 0x00d2d2d2, - 0x00d5d5d5, - 0x00d9d9d9, - 0x00dcdcdc, - 0x00e1e1e1, - 0x00e4e4e4, - 0x00e8e8e8, - 0x00ededed, - 0x00f1f1f1, - 0x00f4f4f4, - 0x00f7f7f7, - 0x00f9f9f9, - 0x00fdfdfd, - 0x00ffffff, + 0x00cccccc, + 0x00cecece, + 0x00d2d2d2, + 0x00d5d5d5, + 0x00d9d9d9, + 0x00dcdcdc, + 0x00e1e1e1, + 0x00e4e4e4, + 0x00e8e8e8, + 0x00ededed, + 0x00f1f1f1, + 0x00f4f4f4, + 0x00f7f7f7, + 0x00f9f9f9, + 0x00fdfdfd, + 0x00ffffff, }; unsigned char const C_app_firmware_bitmap[] = { - 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xcd, 0x79, - 0x35, 0x12, 0x01, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x10, 0x21, 0x53, 0x97, 0xdc, 0xdd, - 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, - 0xdd, 0x8c, 0x14, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x41, 0xc8, 0xdd, 0xdd, 0xdd, - 0xdd, 0xdd, 0xdd, 0xdd, 0x8d, 0x02, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x20, 0xd8, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, - 0xbd, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0xdb, - 0xdd, 0xdd, 0xdd, 0xdd, 0x2b, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0xb2, 0xdd, 0xdd, 0xdd, - 0xbd, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x20, 0xdb, 0xdd, 0xdd, 0x4d, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0xd4, 0xdd, - 0xdd, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x80, 0xdd, 0xcd, 0x02, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x20, - 0xdc, 0x8d, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0xd8, 0x4d, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0xd4, 0x1c, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0xc1, 0x09, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x90, 0x07, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x20, 0x8a, 0x10, 0x7b, - 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x70, - 0x05, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x80, 0xff, 0xb8, 0xff, 0x02, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x50, 0x03, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x30, 0xff, 0xff, - 0xaf, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x30, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0xa1, 0xaa, 0x03, 0x00, - 0x10, 0x73, 0xcf, 0x75, 0xce, 0x24, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x20, 0x01, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x00, - 0xf2, 0xff, 0x07, 0x10, 0x60, 0xff, 0x3f, - 0x00, 0xf8, 0xff, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x10, 0x01, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0xe3, 0x1a, 0xf6, 0xff, 0x19, - 0xe8, 0x66, 0xff, 0x2f, 0x00, 0xf8, 0xff, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x20, 0xfe, - 0xef, 0xff, 0xff, 0xef, 0xff, 0x6f, 0x84, - 0xbf, 0x65, 0xde, 0x35, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x40, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0x8f, 0x30, 0xff, 0xff, 0xaf, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0xf8, 0xff, 0xaf, 0x98, 0xfe, 0xff, 0x1b, - 0x80, 0xff, 0xb9, 0xff, 0x02, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0xf6, 0xef, 0x05, - 0x00, 0xc2, 0xff, 0x0a, 0x30, 0x8a, 0x20, - 0x7c, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0xca, 0xff, 0x8f, 0x00, 0x00, 0x40, 0xff, - 0xcf, 0x3a, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0x4f, - 0x00, 0x00, 0x00, 0xfe, 0xff, 0x5f, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0xff, 0xff, 0x4f, 0x00, 0x00, 0x00, - 0xfe, 0xff, 0x5f, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0xc9, 0xfe, - 0x8f, 0x00, 0x00, 0x40, 0xff, 0xef, 0x3b, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0xf6, 0xef, 0x05, 0x00, - 0xc2, 0xff, 0x0a, 0x30, 0x8a, 0x10, 0x7c, - 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0xf7, 0xff, 0xaf, 0x98, 0xfe, 0xff, 0x1b, - 0x80, 0xff, 0xb8, 0xff, 0x02, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x40, 0xfe, 0xff, 0xff, - 0xff, 0xff, 0xff, 0x8f, 0x30, 0xff, 0xff, - 0xaf, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x20, 0xfd, 0xef, 0xff, 0xff, 0xef, 0xff, - 0x6f, 0x84, 0xbf, 0x65, 0xde, 0x35, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0xd3, 0x2a, - 0xf6, 0xff, 0x1a, 0xf8, 0x66, 0xff, 0x3f, - 0x00, 0xf8, 0xff, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x10, 0x01, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x10, 0x01, 0xf2, 0xff, 0x07, - 0x10, 0x60, 0xff, 0x3f, 0x00, 0xf8, 0xff, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x02, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0xa1, 0xaa, 0x04, 0x00, 0x10, 0x73, - 0xcf, 0x75, 0xce, 0x24, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x20, 0x03, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x30, 0xff, 0xff, 0xaf, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x30, - 0x05, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x80, 0xff, 0xb8, 0xff, 0x02, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x50, 0x07, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x20, 0x8a, 0x20, - 0x7b, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x70, 0x09, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x90, 0x1c, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0xc1, 0x4d, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0xd4, 0x8d, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0xd8, 0xcd, 0x02, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x20, 0xdc, - 0xdd, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x80, 0xdd, 0xdd, 0x4d, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xd4, - 0xdd, 0xdd, 0xbd, 0x02, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x20, 0xdb, 0xdd, 0xdd, 0xdd, - 0x2b, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xb2, - 0xdd, 0xdd, 0xdd, 0xdd, 0xbd, 0x04, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x40, 0xdb, 0xdd, 0xdd, 0xdd, - 0xdd, 0xdd, 0x8d, 0x02, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x20, 0xd8, - 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, - 0x8c, 0x14, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x41, 0xc8, 0xdd, 0xdd, 0xdd, 0xdd, - 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xcd, 0x79, - 0x35, 0x12, 0x01, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x10, 0x21, 0x53, 0x97, 0xdc, 0xdd, - 0xdd, 0xdd, 0xdd, 0xdd, }; - -#define GLYPH_badge_blue_WIDTH 50 - #define GLYPH_badge_blue_HEIGHT 50 - #define GLYPH_badge_blue_BPP 2 - unsigned int const C_badge_blue_colors[] = { - 0x00cccccc, - 0x00dddddd, - 0x00eeeeee, - 0x00f9f9f9, -}; - unsigned char const C_badge_blue_bitmap[] = { - 0xff, 0xff, 0xff, 0xff, 0xaf, 0x05, 0x00, 0xe5, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0x5f, 0x00, 0x00, 0x00, 0x40, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0x1b, 0x00, 0x00, 0x00, 0x00, 0x40, 0xfe, 0xff, 0xff, 0xff, 0xff, - 0xff, 0x1f, 0x00, 0x94, 0xfe, 0x6b, 0x01, 0x40, 0xff, 0xff, 0xff, 0xff, 0xff, - 0x2f, 0x00, 0xf9, 0xff, 0xff, 0xff, 0x06, 0x80, 0xff, 0xff, 0xff, 0xff, 0x7f, - 0x00, 0xf9, 0xff, 0xff, 0xff, 0xff, 0x06, 0xd0, 0xff, 0xff, 0xff, 0xff, 0x01, - 0xf8, 0xff, 0xff, 0xff, 0xff, 0xff, 0x02, 0xf4, 0xff, 0xff, 0xff, 0x07, 0xf4, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x01, 0xfd, 0xff, 0xff, 0x1f, 0xd0, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0x7f, 0x40, 0xff, 0xff, 0x7f, 0x80, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0x2f, 0xd0, 0xff, 0xff, 0x02, 0xfd, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0x07, 0xf8, 0xff, 0x0f, 0xf4, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0x01, 0xff, 0x7f, 0xc0, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0x3f, 0xd0, 0xff, 0x02, 0xfe, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0x0b, 0xf8, 0x1f, 0xf4, 0xff, 0xff, 0x0b, 0x00, 0x00, - 0x00, 0xfe, 0xff, 0xff, 0x41, 0xff, 0x80, 0xff, 0xff, 0x3f, 0x00, 0x00, 0x00, - 0xc0, 0xff, 0xff, 0x2f, 0xf0, 0x07, 0xfd, 0xff, 0xff, 0x03, 0x00, 0x00, 0x00, - 0xfc, 0xff, 0xff, 0x07, 0x3d, 0xe0, 0xff, 0xff, 0x3f, 0xf0, 0xff, 0xff, 0xc0, - 0xff, 0xff, 0xbf, 0xc0, 0x02, 0xff, 0xff, 0xff, 0x03, 0xff, 0xff, 0x0f, 0xfc, - 0xff, 0xff, 0x0f, 0x28, 0xf4, 0xff, 0xff, 0x3f, 0xf0, 0xff, 0xff, 0xc0, 0xff, - 0xff, 0xff, 0x81, 0x41, 0xff, 0xff, 0xff, 0x03, 0xff, 0xff, 0x0f, 0xfc, 0xff, - 0xff, 0x1f, 0x14, 0xf8, 0xff, 0xff, 0x3f, 0xf0, 0xff, 0xff, 0xc0, 0xff, 0xff, - 0xff, 0x42, 0x80, 0xff, 0xff, 0xff, 0x03, 0xff, 0xff, 0x0f, 0xfc, 0xff, 0xff, - 0x2f, 0x00, 0xfc, 0xff, 0xff, 0x3f, 0xf0, 0xff, 0xff, 0xc0, 0xff, 0xff, 0xff, - 0x03, 0xc0, 0xff, 0xff, 0xff, 0x03, 0xff, 0xff, 0x0f, 0xfc, 0xff, 0xff, 0x3f, - 0x00, 0xfc, 0xff, 0xff, 0x3f, 0xf0, 0xff, 0xff, 0xc0, 0xff, 0xff, 0xff, 0x03, - 0xc0, 0xff, 0xff, 0xff, 0x03, 0xff, 0xff, 0x0f, 0xfc, 0xff, 0xff, 0x3f, 0x00, - 0xf8, 0xff, 0xff, 0x3f, 0xf0, 0xff, 0xff, 0xc0, 0xff, 0xff, 0xff, 0x02, 0x81, - 0xff, 0xff, 0xff, 0x03, 0xff, 0xff, 0x0f, 0xfc, 0xff, 0xff, 0x2f, 0x14, 0xf4, - 0xff, 0xff, 0x3f, 0xf0, 0xff, 0xff, 0xc0, 0xff, 0xff, 0xff, 0x41, 0x42, 0xff, - 0xff, 0xff, 0x03, 0xff, 0xff, 0x0f, 0xfc, 0xff, 0xff, 0x1f, 0x28, 0xf0, 0xff, - 0xff, 0x3f, 0xf0, 0xff, 0xff, 0xc0, 0xff, 0xff, 0xff, 0x80, 0x03, 0xfe, 0xff, - 0xff, 0x03, 0xff, 0xff, 0x0f, 0xfc, 0xff, 0xff, 0x0b, 0x7c, 0xd0, 0xff, 0xff, - 0x3f, 0x00, 0x00, 0x00, 0xc0, 0xff, 0xff, 0x7f, 0xd0, 0x0f, 0xf8, 0xff, 0xff, - 0x03, 0x00, 0x00, 0x00, 0xfc, 0xff, 0xff, 0x02, 0xff, 0x41, 0xff, 0xff, 0xbf, - 0x00, 0x00, 0x00, 0xe0, 0xff, 0xff, 0x1f, 0xf4, 0x2f, 0xe0, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xbf, 0x80, 0xff, 0x07, 0xfc, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0x03, 0xfd, 0xff, 0x40, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0x1f, 0xf0, 0xff, 0x2f, 0xd0, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0x7f, 0x80, 0xff, 0xff, 0x07, 0xf8, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0x02, 0xfd, 0xff, 0xff, 0x01, 0xfd, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0x07, 0xf4, 0xff, 0xff, 0x7f, 0x40, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0x1f, 0xd0, 0xff, 0xff, 0xff, 0x1f, 0x80, 0xff, 0xff, 0xff, 0xff, 0xff, - 0x2f, 0x40, 0xff, 0xff, 0xff, 0xff, 0x07, 0x90, 0xff, 0xff, 0xff, 0xff, 0x6f, - 0x00, 0xfd, 0xff, 0xff, 0xff, 0xff, 0x02, 0x90, 0xff, 0xff, 0xff, 0x6f, 0x00, - 0xf8, 0xff, 0xff, 0xff, 0xff, 0xff, 0x01, 0x40, 0xe9, 0xbf, 0x16, 0x00, 0xf4, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xbf, 0x01, 0x00, 0x00, 0x00, 0x00, 0xe4, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x01, 0x00, 0x00, 0x00, 0xf4, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x5a, 0x00, 0x50, 0xfa, 0xff, 0xff, 0xff, - 0xff, }; - - -#define GLYPH_icon_brightness_high_WIDTH 18 - #define GLYPH_icon_brightness_high_HEIGHT 18 - #define GLYPH_icon_brightness_high_BPP 2 - unsigned int const C_icon_brightness_high_colors[] = { - 0x00cccccc, - 0x00e5e5e5, - 0x00f8f8f8, - 0x00f9f9f9, -}; - unsigned char const C_icon_brightness_high_bitmap[] = { - 0xff, 0xff, 0xf5, 0xff, 0xff, - 0xff, 0x0f, 0xff, 0xff, 0x6f, - 0xff, 0xf5, 0x9f, 0xff, 0xd1, - 0xff, 0x7f, 0xf4, 0x6f, 0xbd, - 0xea, 0x97, 0xff, 0xff, 0x01, - 0xf4, 0xff, 0xff, 0x07, 0x05, - 0xfd, 0xff, 0x2f, 0xf8, 0x82, - 0xff, 0xd1, 0xd1, 0x7f, 0x74, - 0x14, 0x1d, 0xfd, 0x47, 0x47, - 0xff, 0xd2, 0x7f, 0xf8, 0xff, - 0x7f, 0x54, 0xd1, 0xff, 0xff, - 0x1b, 0x40, 0xfe, 0xff, 0xd7, - 0x5b, 0x7e, 0xfd, 0x1f, 0xfd, - 0xff, 0x47, 0xff, 0xe5, 0x5f, - 0xbf, 0xf5, 0xff, 0xff, 0xf0, - 0xff, 0xff, 0xff, 0x5f, 0xff, - 0xff, }; - - -#define GLYPH_icon_brightness_low_WIDTH 18 - #define GLYPH_icon_brightness_low_HEIGHT 18 - #define GLYPH_icon_brightness_low_BPP 2 - unsigned int const C_icon_brightness_low_colors[] = { - 0x00cccccc, - 0x00dcdcdc, - 0x00e5e5e5, - 0x00f9f9f9, -}; - unsigned char const C_icon_brightness_low_bitmap[] = { - 0xff, 0xff, 0xf5, 0xff, 0xff, - 0xff, 0x5f, 0xff, 0xff, 0xbf, - 0xff, 0xfa, 0xef, 0xff, 0xe2, - 0xff, 0xbf, 0xf8, 0x7f, 0xfe, - 0xff, 0xdb, 0xff, 0xff, 0x02, - 0xf8, 0xff, 0xff, 0x0b, 0x00, - 0xfe, 0xff, 0x3f, 0x00, 0xc0, - 0xff, 0xe5, 0x02, 0x00, 0xb8, - 0x55, 0x2e, 0x00, 0x80, 0x5b, - 0xff, 0x03, 0x00, 0xfc, 0xff, - 0xbf, 0x00, 0xe0, 0xff, 0xff, - 0x2f, 0x80, 0xff, 0xff, 0xeb, - 0xaf, 0xbf, 0xfe, 0x2f, 0xfd, - 0xff, 0x87, 0xff, 0xfa, 0xaf, - 0xff, 0xfa, 0xff, 0xff, 0xf5, - 0xff, 0xff, 0xff, 0x5f, 0xff, - 0xff, }; - - - -#define BAGL_GLYPH_NONE { -1UL, 0, 0, 0, NULL, NULL} + 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xcd, 0x79, 0x35, 0x12, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, + 0x21, 0x53, 0x97, 0xdc, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0x8c, 0x14, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x41, 0xc8, 0xdd, 0xdd, + 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0x8d, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x20, 0xd8, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xbd, 0x04, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x40, 0xdb, 0xdd, 0xdd, 0xdd, 0xdd, 0x2b, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xb2, 0xdd, 0xdd, 0xdd, 0xbd, 0x02, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x20, 0xdb, 0xdd, 0xdd, 0x4d, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xd4, 0xdd, 0xdd, + 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0xdd, 0xcd, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x20, + 0xdc, 0x8d, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xd8, 0x4d, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0xd4, 0x1c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc1, 0x09, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x90, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x20, 0x8a, 0x10, 0x7b, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x70, 0x05, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0xff, 0xb8, 0xff, + 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x50, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x30, 0xff, 0xff, 0xaf, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x30, + 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xa1, 0xaa, 0x03, 0x00, 0x10, 0x73, 0xcf, + 0x75, 0xce, 0x24, 0x00, 0x00, 0x00, 0x00, 0x00, 0x20, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x10, 0x00, 0xf2, 0xff, 0x07, 0x10, 0x60, 0xff, 0x3f, 0x00, 0xf8, 0xff, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x10, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xe3, 0x1a, 0xf6, 0xff, 0x19, 0xe8, 0x66, + 0xff, 0x2f, 0x00, 0xf8, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x20, 0xfe, 0xef, 0xff, 0xff, 0xef, 0xff, 0x6f, 0x84, 0xbf, 0x65, 0xde, 0x35, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0x8f, 0x30, 0xff, 0xff, 0xaf, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0xf8, 0xff, 0xaf, 0x98, 0xfe, 0xff, 0x1b, 0x80, 0xff, 0xb9, 0xff, 0x02, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf6, 0xef, 0x05, + 0x00, 0xc2, 0xff, 0x0a, 0x30, 0x8a, 0x20, 0x7c, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0xca, 0xff, 0x8f, 0x00, 0x00, 0x40, 0xff, 0xcf, 0x3a, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, + 0x4f, 0x00, 0x00, 0x00, 0xfe, 0xff, 0x5f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0x4f, 0x00, 0x00, 0x00, 0xfe, 0xff, 0x5f, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0xc9, 0xfe, 0x8f, 0x00, 0x00, 0x40, 0xff, 0xef, 0x3b, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf6, 0xef, 0x05, 0x00, 0xc2, 0xff, + 0x0a, 0x30, 0x8a, 0x10, 0x7c, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0xf7, 0xff, 0xaf, 0x98, 0xfe, 0xff, 0x1b, 0x80, 0xff, 0xb8, 0xff, 0x02, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0xfe, 0xff, 0xff, 0xff, + 0xff, 0xff, 0x8f, 0x30, 0xff, 0xff, 0xaf, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x20, 0xfd, 0xef, 0xff, 0xff, 0xef, 0xff, 0x6f, 0x84, 0xbf, 0x65, 0xde, + 0x35, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xd3, 0x2a, + 0xf6, 0xff, 0x1a, 0xf8, 0x66, 0xff, 0x3f, 0x00, 0xf8, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, + 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x01, 0xf2, 0xff, 0x07, 0x10, 0x60, 0xff, 0x3f, + 0x00, 0xf8, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0xa1, 0xaa, 0x04, 0x00, 0x10, 0x73, 0xcf, 0x75, 0xce, 0x24, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x20, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x30, 0xff, 0xff, 0xaf, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x30, 0x05, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0xff, 0xb8, 0xff, 0x02, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x50, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x20, 0x8a, 0x20, 0x7b, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x70, 0x09, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x90, 0x1c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc1, 0x4d, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xd4, 0x8d, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0xd8, 0xcd, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x20, 0xdc, 0xdd, 0x08, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x80, 0xdd, 0xdd, 0x4d, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xd4, 0xdd, 0xdd, 0xbd, 0x02, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x20, 0xdb, 0xdd, 0xdd, 0xdd, 0x2b, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xb2, 0xdd, 0xdd, 0xdd, 0xdd, + 0xbd, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x40, 0xdb, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0x8d, 0x02, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x20, 0xd8, 0xdd, 0xdd, 0xdd, + 0xdd, 0xdd, 0xdd, 0xdd, 0x8c, 0x14, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x41, 0xc8, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xcd, 0x79, + 0x35, 0x12, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x21, 0x53, 0x97, 0xdc, 0xdd, 0xdd, 0xdd, + 0xdd, 0xdd, +}; + +#define GLYPH_badge_blue_WIDTH 50 +#define GLYPH_badge_blue_HEIGHT 50 +#define GLYPH_badge_blue_BPP 2 +unsigned int const C_badge_blue_colors[] = { + 0x00cccccc, + 0x00dddddd, + 0x00eeeeee, + 0x00f9f9f9, +}; +unsigned char const C_badge_blue_bitmap[] = { + 0xff, 0xff, 0xff, 0xff, 0xaf, 0x05, 0x00, 0xe5, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0x5f, 0x00, 0x00, 0x00, 0x40, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x1b, 0x00, 0x00, 0x00, + 0x00, 0x40, 0xfe, 0xff, 0xff, 0xff, 0xff, 0xff, 0x1f, 0x00, 0x94, 0xfe, 0x6b, 0x01, 0x40, 0xff, + 0xff, 0xff, 0xff, 0xff, 0x2f, 0x00, 0xf9, 0xff, 0xff, 0xff, 0x06, 0x80, 0xff, 0xff, 0xff, 0xff, + 0x7f, 0x00, 0xf9, 0xff, 0xff, 0xff, 0xff, 0x06, 0xd0, 0xff, 0xff, 0xff, 0xff, 0x01, 0xf8, 0xff, + 0xff, 0xff, 0xff, 0xff, 0x02, 0xf4, 0xff, 0xff, 0xff, 0x07, 0xf4, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0x01, 0xfd, 0xff, 0xff, 0x1f, 0xd0, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x7f, 0x40, 0xff, + 0xff, 0x7f, 0x80, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x2f, 0xd0, 0xff, 0xff, 0x02, 0xfd, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x07, 0xf8, 0xff, 0x0f, 0xf4, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0x01, 0xff, 0x7f, 0xc0, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0x3f, 0xd0, 0xff, 0x02, 0xfe, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x0b, 0xf8, 0x1f, + 0xf4, 0xff, 0xff, 0x0b, 0x00, 0x00, 0x00, 0xfe, 0xff, 0xff, 0x41, 0xff, 0x80, 0xff, 0xff, 0x3f, + 0x00, 0x00, 0x00, 0xc0, 0xff, 0xff, 0x2f, 0xf0, 0x07, 0xfd, 0xff, 0xff, 0x03, 0x00, 0x00, 0x00, + 0xfc, 0xff, 0xff, 0x07, 0x3d, 0xe0, 0xff, 0xff, 0x3f, 0xf0, 0xff, 0xff, 0xc0, 0xff, 0xff, 0xbf, + 0xc0, 0x02, 0xff, 0xff, 0xff, 0x03, 0xff, 0xff, 0x0f, 0xfc, 0xff, 0xff, 0x0f, 0x28, 0xf4, 0xff, + 0xff, 0x3f, 0xf0, 0xff, 0xff, 0xc0, 0xff, 0xff, 0xff, 0x81, 0x41, 0xff, 0xff, 0xff, 0x03, 0xff, + 0xff, 0x0f, 0xfc, 0xff, 0xff, 0x1f, 0x14, 0xf8, 0xff, 0xff, 0x3f, 0xf0, 0xff, 0xff, 0xc0, 0xff, + 0xff, 0xff, 0x42, 0x80, 0xff, 0xff, 0xff, 0x03, 0xff, 0xff, 0x0f, 0xfc, 0xff, 0xff, 0x2f, 0x00, + 0xfc, 0xff, 0xff, 0x3f, 0xf0, 0xff, 0xff, 0xc0, 0xff, 0xff, 0xff, 0x03, 0xc0, 0xff, 0xff, 0xff, + 0x03, 0xff, 0xff, 0x0f, 0xfc, 0xff, 0xff, 0x3f, 0x00, 0xfc, 0xff, 0xff, 0x3f, 0xf0, 0xff, 0xff, + 0xc0, 0xff, 0xff, 0xff, 0x03, 0xc0, 0xff, 0xff, 0xff, 0x03, 0xff, 0xff, 0x0f, 0xfc, 0xff, 0xff, + 0x3f, 0x00, 0xf8, 0xff, 0xff, 0x3f, 0xf0, 0xff, 0xff, 0xc0, 0xff, 0xff, 0xff, 0x02, 0x81, 0xff, + 0xff, 0xff, 0x03, 0xff, 0xff, 0x0f, 0xfc, 0xff, 0xff, 0x2f, 0x14, 0xf4, 0xff, 0xff, 0x3f, 0xf0, + 0xff, 0xff, 0xc0, 0xff, 0xff, 0xff, 0x41, 0x42, 0xff, 0xff, 0xff, 0x03, 0xff, 0xff, 0x0f, 0xfc, + 0xff, 0xff, 0x1f, 0x28, 0xf0, 0xff, 0xff, 0x3f, 0xf0, 0xff, 0xff, 0xc0, 0xff, 0xff, 0xff, 0x80, + 0x03, 0xfe, 0xff, 0xff, 0x03, 0xff, 0xff, 0x0f, 0xfc, 0xff, 0xff, 0x0b, 0x7c, 0xd0, 0xff, 0xff, + 0x3f, 0x00, 0x00, 0x00, 0xc0, 0xff, 0xff, 0x7f, 0xd0, 0x0f, 0xf8, 0xff, 0xff, 0x03, 0x00, 0x00, + 0x00, 0xfc, 0xff, 0xff, 0x02, 0xff, 0x41, 0xff, 0xff, 0xbf, 0x00, 0x00, 0x00, 0xe0, 0xff, 0xff, + 0x1f, 0xf4, 0x2f, 0xe0, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xbf, 0x80, 0xff, 0x07, + 0xfc, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x03, 0xfd, 0xff, 0x40, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0x1f, 0xf0, 0xff, 0x2f, 0xd0, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0x7f, 0x80, 0xff, 0xff, 0x07, 0xf8, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x02, 0xfd, + 0xff, 0xff, 0x01, 0xfd, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x07, 0xf4, 0xff, 0xff, 0x7f, 0x40, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x1f, 0xd0, 0xff, 0xff, 0xff, 0x1f, 0x80, 0xff, 0xff, 0xff, + 0xff, 0xff, 0x2f, 0x40, 0xff, 0xff, 0xff, 0xff, 0x07, 0x90, 0xff, 0xff, 0xff, 0xff, 0x6f, 0x00, + 0xfd, 0xff, 0xff, 0xff, 0xff, 0x02, 0x90, 0xff, 0xff, 0xff, 0x6f, 0x00, 0xf8, 0xff, 0xff, 0xff, + 0xff, 0xff, 0x01, 0x40, 0xe9, 0xbf, 0x16, 0x00, 0xf4, 0xff, 0xff, 0xff, 0xff, 0xff, 0xbf, 0x01, + 0x00, 0x00, 0x00, 0x00, 0xe4, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x01, 0x00, 0x00, 0x00, + 0xf4, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x5a, 0x00, 0x50, 0xfa, 0xff, 0xff, 0xff, + 0xff, +}; + +#define GLYPH_icon_brightness_high_WIDTH 18 +#define GLYPH_icon_brightness_high_HEIGHT 18 +#define GLYPH_icon_brightness_high_BPP 2 +unsigned int const C_icon_brightness_high_colors[] = { + 0x00cccccc, + 0x00e5e5e5, + 0x00f8f8f8, + 0x00f9f9f9, +}; +unsigned char const C_icon_brightness_high_bitmap[] = { + 0xff, 0xff, 0xf5, 0xff, 0xff, 0xff, 0x0f, 0xff, 0xff, 0x6f, 0xff, 0xf5, 0x9f, 0xff, + 0xd1, 0xff, 0x7f, 0xf4, 0x6f, 0xbd, 0xea, 0x97, 0xff, 0xff, 0x01, 0xf4, 0xff, 0xff, + 0x07, 0x05, 0xfd, 0xff, 0x2f, 0xf8, 0x82, 0xff, 0xd1, 0xd1, 0x7f, 0x74, 0x14, 0x1d, + 0xfd, 0x47, 0x47, 0xff, 0xd2, 0x7f, 0xf8, 0xff, 0x7f, 0x54, 0xd1, 0xff, 0xff, 0x1b, + 0x40, 0xfe, 0xff, 0xd7, 0x5b, 0x7e, 0xfd, 0x1f, 0xfd, 0xff, 0x47, 0xff, 0xe5, 0x5f, + 0xbf, 0xf5, 0xff, 0xff, 0xf0, 0xff, 0xff, 0xff, 0x5f, 0xff, 0xff, +}; + +#define GLYPH_icon_brightness_low_WIDTH 18 +#define GLYPH_icon_brightness_low_HEIGHT 18 +#define GLYPH_icon_brightness_low_BPP 2 +unsigned int const C_icon_brightness_low_colors[] = { + 0x00cccccc, + 0x00dcdcdc, + 0x00e5e5e5, + 0x00f9f9f9, +}; +unsigned char const C_icon_brightness_low_bitmap[] = { + 0xff, 0xff, 0xf5, 0xff, 0xff, 0xff, 0x5f, 0xff, 0xff, 0xbf, 0xff, 0xfa, 0xef, 0xff, + 0xe2, 0xff, 0xbf, 0xf8, 0x7f, 0xfe, 0xff, 0xdb, 0xff, 0xff, 0x02, 0xf8, 0xff, 0xff, + 0x0b, 0x00, 0xfe, 0xff, 0x3f, 0x00, 0xc0, 0xff, 0xe5, 0x02, 0x00, 0xb8, 0x55, 0x2e, + 0x00, 0x80, 0x5b, 0xff, 0x03, 0x00, 0xfc, 0xff, 0xbf, 0x00, 0xe0, 0xff, 0xff, 0x2f, + 0x80, 0xff, 0xff, 0xeb, 0xaf, 0xbf, 0xfe, 0x2f, 0xfd, 0xff, 0x87, 0xff, 0xfa, 0xaf, + 0xff, 0xfa, 0xff, 0xff, 0xf5, 0xff, 0xff, 0xff, 0x5f, 0xff, 0xff, +}; + +#define BAGL_GLYPH_NONE \ + { \ + -1UL, 0, 0, 0, NULL, NULL \ + } const bagl_glyph_array_entry_t const C_glyph_array[] = { - BAGL_GLYPH_NONE, // icon_id = 0 + BAGL_GLYPH_NONE, // icon_id = 0 #ifdef HAVE_BAGL_GLYPH_LOGO_LEDGER_100 - {BAGL_GLYPH_LOGO_LEDGER_100, 101, 104, 4, C_logo_ledger_colors, C_logo_ledger_bitmap}, + {BAGL_GLYPH_LOGO_LEDGER_100, 101, 104, 4, C_logo_ledger_colors, C_logo_ledger_bitmap }, #endif #ifdef HAVE_BAGL_GLYPH_LOGO_LEDGER_BLUE_120 - {BAGL_GLYPH_LOGO_LEDGER_BLUE_120, 120, 72, 4, C_logo_ledger_blue_colors, C_logo_ledger_blue_bitmap}, + {BAGL_GLYPH_LOGO_LEDGER_BLUE_120, + 120, 72, + 4, C_logo_ledger_blue_colors, + C_logo_ledger_blue_bitmap }, #endif #ifdef HAVE_BAGL_GLYPH_ICON_GEARS_50 - {BAGL_GLYPH_ICON_GEARS_50, 50, 50, 2, C_icon_bootloader_colors, C_icon_bootloader_bitmap}, + {BAGL_GLYPH_ICON_GEARS_50, 50, 50, 2, C_icon_bootloader_colors, C_icon_bootloader_bitmap }, #endif #ifdef HAVE_BAGL_GLYPH_ICON_CLEAR_16 - {BAGL_GLYPH_ICON_CLEAR_16, 16, 16, 2, C_icon_clear_colors, C_icon_clear_bitmap}, + {BAGL_GLYPH_ICON_CLEAR_16, 16, 16, 2, C_icon_clear_colors, C_icon_clear_bitmap }, #endif #ifdef HAVE_BAGL_GLYPH_ICON_BACKSPACE_20 - {BAGL_GLYPH_ICON_BACKSPACE_20, 20, 14, 2, C_icon_backspace_colors, C_icon_backspace_bitmap}, + {BAGL_GLYPH_ICON_BACKSPACE_20, 20, 14, 2, C_icon_backspace_colors, C_icon_backspace_bitmap }, #endif #ifdef HAVE_BAGL_GLYPH_ICON_CHECK - {BAGL_GLYPH_ICON_CHECK, 8, 6, 1, C_icon_check_colors, C_icon_check_bitmap}, + {BAGL_GLYPH_ICON_CHECK, 8, 6, 1, C_icon_check_colors, C_icon_check_bitmap }, #endif #ifdef HAVE_BAGL_GLYPH_ICON_CROSS - {BAGL_GLYPH_ICON_CROSS, 7, 7, 1, C_icon_cross_colors, C_icon_cross_bitmap}, + {BAGL_GLYPH_ICON_CROSS, 7, 7, 1, C_icon_cross_colors, C_icon_cross_bitmap }, #endif #ifdef HAVE_BAGL_GLYPH_ICON_CHECK_BADGE - {BAGL_GLYPH_ICON_CHECK_BADGE, 14, 14, 1, C_badge_validate_colors, C_badge_validate_bitmap}, + {BAGL_GLYPH_ICON_CHECK_BADGE, 14, 14, 1, C_badge_validate_colors, C_badge_validate_bitmap }, #endif #ifdef HAVE_BAGL_GLYPH_ICON_LEFT - {BAGL_GLYPH_ICON_LEFT, 4, 7, 1, C_icon_left_colors, C_icon_left_bitmap}, + {BAGL_GLYPH_ICON_LEFT, 4, 7, 1, C_icon_left_colors, C_icon_left_bitmap }, #endif #ifdef HAVE_BAGL_GLYPH_ICON_RIGHT - {BAGL_GLYPH_ICON_RIGHT, 4, 7, 1, C_icon_right_colors, C_icon_right_bitmap}, + {BAGL_GLYPH_ICON_RIGHT, 4, 7, 1, C_icon_right_colors, C_icon_right_bitmap }, #endif #ifdef HAVE_BAGL_GLYPH_ICON_UP - {BAGL_GLYPH_ICON_UP, 7, 4, 1, C_icon_up_colors, C_icon_up_bitmap}, + {BAGL_GLYPH_ICON_UP, 7, 4, 1, C_icon_up_colors, C_icon_up_bitmap }, #endif #ifdef HAVE_BAGL_GLYPH_ICON_DOWN - {BAGL_GLYPH_ICON_DOWN, 7, 4, 1, C_icon_down_colors, C_icon_down_bitmap}, + {BAGL_GLYPH_ICON_DOWN, 7, 4, 1, C_icon_down_colors, C_icon_down_bitmap }, #endif #ifdef HAVE_BAGL_GLYPH_LOGO_LEDGER_MINI - {BAGL_GLYPH_LOGO_LEDGER_MINI, 16, 16, 1, C_logo_ledger_mini_colors, C_logo_ledger_mini_bitmap}, + {BAGL_GLYPH_LOGO_LEDGER_MINI, 16, 16, 1, C_logo_ledger_mini_colors, C_logo_ledger_mini_bitmap }, #endif #ifdef HAVE_BAGL_GLYPH_ICON_CROSS_BADGE - {BAGL_GLYPH_ICON_CROSS_BADGE, 14, 14, 1, C_icon_cross_badge_colors, C_icon_cross_badge_bitmap}, + {BAGL_GLYPH_ICON_CROSS_BADGE, 14, 14, 1, C_icon_cross_badge_colors, C_icon_cross_badge_bitmap }, #endif #ifdef HAVE_BAGL_GLYPH_ICON_DASHBOARD_BADGE - {BAGL_GLYPH_ICON_DASHBOARD_BADGE, 14, 14, 1, C_badge_dashboard_colors, C_badge_dashboard_bitmap}, + {BAGL_GLYPH_ICON_DASHBOARD_BADGE, + 14, 14, + 1, C_badge_dashboard_colors, + C_badge_dashboard_bitmap }, #endif #ifdef HAVE_BAGL_GLYPH_ICON_PLUS - {BAGL_GLYPH_ICON_PLUS, 7, 7, 1, C_icon_plus_colors, C_icon_plus_bitmap}, + {BAGL_GLYPH_ICON_PLUS, 7, 7, 1, C_icon_plus_colors, C_icon_plus_bitmap }, #endif #ifdef HAVE_BAGL_GLYPH_ICON_LESS - {BAGL_GLYPH_ICON_LESS, 6, 1, 1, C_icon_less_colors, C_icon_less_bitmap}, + {BAGL_GLYPH_ICON_LESS, 6, 1, 1, C_icon_less_colors, C_icon_less_bitmap }, #endif #ifdef HAVE_BAGL_GLYPH_ICON_TOGGLE_ON - {BAGL_GLYPH_ICON_TOGGLE_ON, 16, 10, 1, C_toggle_on_colors, C_toggle_on_bitmap}, + {BAGL_GLYPH_ICON_TOGGLE_ON, 16, 10, 1, C_toggle_on_colors, C_toggle_on_bitmap }, #endif #ifdef HAVE_BAGL_GLYPH_ICON_TOGGLE_OFF - {BAGL_GLYPH_ICON_TOGGLE_OFF, 16, 10, 1, C_toggle_off_colors, C_toggle_off_bitmap}, + {BAGL_GLYPH_ICON_TOGGLE_OFF, 16, 10, 1, C_toggle_off_colors, C_toggle_off_bitmap }, #endif #ifdef HAVE_BAGL_GLYPH_ICON_LOADING_BADGE - {BAGL_GLYPH_ICON_LOADING_BADGE, 14, 14, 1, C_badge_loading_colors, C_badge_loading_bitmap}, + {BAGL_GLYPH_ICON_LOADING_BADGE, 14, 14, 1, C_badge_loading_colors, C_badge_loading_bitmap }, #endif #ifdef HAVE_BAGL_GLYPH_ICON_COG_BADGE - {BAGL_GLYPH_ICON_COG_BADGE, 16, 16, 1, C_app_settings_colors, C_app_settings_bitmap}, + {BAGL_GLYPH_ICON_COG_BADGE, 16, 16, 1, C_app_settings_colors, C_app_settings_bitmap }, #endif #ifdef HAVE_BAGL_GLYPH_ICON_WARNING_BADGE - {BAGL_GLYPH_ICON_WARNING_BADGE, 14, 14, 1, C_badge_warning_colors, C_badge_warning_bitmap}, + {BAGL_GLYPH_ICON_WARNING_BADGE, 14, 14, 1, C_badge_warning_colors, C_badge_warning_bitmap }, #endif #ifdef HAVE_BAGL_GLYPH_ICON_DOWNLOAD_BADGE - {BAGL_GLYPH_ICON_DOWNLOAD_BADGE, 14, 14, 1, C_badge_install_colors, C_badge_install_bitmap}, + {BAGL_GLYPH_ICON_DOWNLOAD_BADGE, 14, 14, 1, C_badge_install_colors, C_badge_install_bitmap }, #endif #ifdef HAVE_BAGL_GLYPH_ICON_TRANSACTION_BADGE - {BAGL_GLYPH_ICON_TRANSACTION_BADGE, 14, 14, 1, C_badge_transaction_colors, C_badge_transaction_bitmap}, + {BAGL_GLYPH_ICON_TRANSACTION_BADGE, + 14, 14, + 1, C_badge_transaction_colors, + C_badge_transaction_bitmap }, #endif #ifdef HAVE_BAGL_GLYPH_ICON_BITCOIN_BADGE - {BAGL_GLYPH_ICON_BITCOIN_BADGE, 14, 14, 1, C_badge_bitcoin_colors, C_badge_bitcoin_bitmap}, + {BAGL_GLYPH_ICON_BITCOIN_BADGE, 14, 14, 1, C_badge_bitcoin_colors, C_badge_bitcoin_bitmap }, #endif #ifdef HAVE_BAGL_GLYPH_ICON_ETHEREUM_BADGE - {BAGL_GLYPH_ICON_ETHEREUM_BADGE, 14, 14, 1, C_badge_ethereum_colors, C_badge_ethereum_bitmap}, + {BAGL_GLYPH_ICON_ETHEREUM_BADGE, 14, 14, 1, C_badge_ethereum_colors, C_badge_ethereum_bitmap }, #endif #ifdef HAVE_BAGL_GLYPH_ICON_EYE_BADGE - {BAGL_GLYPH_ICON_EYE_BADGE, 14, 14, 1, C_badge_eye_colors, C_badge_eye_bitmap}, + {BAGL_GLYPH_ICON_EYE_BADGE, 14, 14, 1, C_badge_eye_colors, C_badge_eye_bitmap }, #endif #ifdef HAVE_BAGL_GLYPH_ICON_PEOPLE_BADGE - {BAGL_GLYPH_ICON_PEOPLE_BADGE, 14, 14, 1, C_badge_people_colors, C_badge_people_bitmap}, + {BAGL_GLYPH_ICON_PEOPLE_BADGE, 14, 14, 1, C_badge_people_colors, C_badge_people_bitmap }, #endif #ifdef HAVE_BAGL_GLYPH_ICON_LOCK_BADGE - {BAGL_GLYPH_ICON_LOCK_BADGE, 14, 14, 1, C_badge_lock_colors, C_badge_lock_bitmap}, + {BAGL_GLYPH_ICON_LOCK_BADGE, 14, 14, 1, C_badge_lock_colors, C_badge_lock_bitmap }, #endif #ifdef HAVE_BAGL_GLYPH_ICON_BLUE_CABLE - {BAGL_GLYPH_ICON_BLUE_CABLE, 65, 62, 2, C_icon_blue_cable_colors, C_icon_blue_cable_bitmap}, + {BAGL_GLYPH_ICON_BLUE_CABLE, 65, 62, 2, C_icon_blue_cable_colors, C_icon_blue_cable_bitmap }, #endif #ifdef HAVE_BAGL_GLYPH_TEXT_WELCOME - {BAGL_GLYPH_TEXT_WELCOME, 113, 24, 4, C_text_welcome_colors, C_text_welcome_bitmap}, + {BAGL_GLYPH_TEXT_WELCOME, 113, 24, 4, C_text_welcome_colors, C_text_welcome_bitmap }, #endif #ifdef HAVE_BAGL_GLYPH_LOGO_LEDGER_BOOT - {BAGL_GLYPH_LOGO_LEDGER_BOOT, 50, 50, 4, C_logo_ledger_boot_colors, C_logo_ledger_boot_bitmap}, + {BAGL_GLYPH_LOGO_LEDGER_BOOT, 50, 50, 4, C_logo_ledger_boot_colors, C_logo_ledger_boot_bitmap }, #endif #ifdef HAVE_BAGL_GLYPH_BATT_LEFT - {BAGL_GLYPH_BATT_LEFT, 4, 40, 2, C_icon_battery_left_colors, C_icon_battery_left_bitmap}, + {BAGL_GLYPH_BATT_LEFT, 4, 40, 2, C_icon_battery_left_colors, C_icon_battery_left_bitmap }, #endif #ifdef HAVE_BAGL_GLYPH_BATT_RIGHT - {BAGL_GLYPH_BATT_RIGHT, 4, 40, 2, C_icon_battery_right_colors, C_icon_battery_right_bitmap}, + {BAGL_GLYPH_BATT_RIGHT, 4, 40, 2, C_icon_battery_right_colors, C_icon_battery_right_bitmap}, #endif #ifdef HAVE_BAGL_GLYPH_ICON_LIGHTNING - {BAGL_GLYPH_ICON_LIGHTNING, 17, 24, 4, C_icon_lightning_colors, C_icon_lightning_bitmap}, + {BAGL_GLYPH_ICON_LIGHTNING, 17, 24, 4, C_icon_lightning_colors, C_icon_lightning_bitmap }, #endif #ifdef HAVE_BAGL_GLYPH_ICON_PLUG - {BAGL_GLYPH_ICON_PLUG, 24, 15, 4, C_icon_plug_colors, C_icon_plug_bitmap}, + {BAGL_GLYPH_ICON_PLUG, 24, 15, 4, C_icon_plug_colors, C_icon_plug_bitmap }, #endif #ifdef HAVE_BAGL_GLYPH_BADGE_DOWNLOAD_BLUE - {BAGL_GLYPH_BADGE_DOWNLOAD_BLUE, 50, 50, 2, C_badge_download_blue_colors, C_badge_download_blue_bitmap}, + {BAGL_GLYPH_BADGE_DOWNLOAD_BLUE, + 50, 50, + 2, C_badge_download_blue_colors, + C_badge_download_blue_bitmap }, #endif #ifdef HAVE_BAGL_GLYPH_BADGE_WARNING_BLUE - {BAGL_GLYPH_BADGE_WARNING_BLUE, 50, 50, 2, C_badge_warning_blue_colors, C_badge_warning_blue_bitmap}, + {BAGL_GLYPH_BADGE_WARNING_BLUE, + 50, 50, + 2, C_badge_warning_blue_colors, + C_badge_warning_blue_bitmap }, #endif #ifdef HAVE_BAGL_GLYPH_ICON_LOADER_BLUE - {BAGL_GLYPH_ICON_LOADER_BLUE, 50, 50, 2, C_loader_blue_colors, C_loader_blue_bitmap}, + {BAGL_GLYPH_ICON_LOADER_BLUE, 50, 50, 2, C_loader_blue_colors, C_loader_blue_bitmap }, #endif #ifdef HAVE_BAGL_GLYPH_BADGE_CHECKMARK_BLUE - {BAGL_GLYPH_BADGE_CHECKMARK_BLUE, 50, 50, 2, C_badge_checkmark_blue_colors, C_badge_checkmark_blue_bitmap}, + {BAGL_GLYPH_BADGE_CHECKMARK_BLUE, + 50, 50, + 2, C_badge_checkmark_blue_colors, + C_badge_checkmark_blue_bitmap }, #endif #ifdef HAVE_BAGL_GLYPH_BADGE_WRENCH_BLUE - {BAGL_GLYPH_BADGE_WRENCH_BLUE, 50, 50, 2, C_badge_wrench_colors, C_badge_wrench_bitmap}, -#endif // HAVE_BAGL_GLYPH_BADGE_WRENCH_BLUE + {BAGL_GLYPH_BADGE_WRENCH_BLUE, 50, 50, 2, C_badge_wrench_colors, C_badge_wrench_bitmap }, +#endif // HAVE_BAGL_GLYPH_BADGE_WRENCH_BLUE #ifdef HAVE_BAGL_GLYPH_BADGE_POWER_BLUE - {BAGL_GLYPH_BADGE_POWER_BLUE, 50, 50, 2, C_badge_power_colors, C_badge_power_bitmap}, -#endif // HAVE_BAGL_GLYPH_BADGE_POWER_BLUE + {BAGL_GLYPH_BADGE_POWER_BLUE, 50, 50, 2, C_badge_power_colors, C_badge_power_bitmap }, +#endif // HAVE_BAGL_GLYPH_BADGE_POWER_BLUE #ifdef HAVE_BAGL_GLYPH_BADGE_ERROR_BLUE - {BAGL_GLYPH_BADGE_ERROR_BLUE, 50, 50, 2, C_badge_error_colors, C_badge_error_bitmap}, -#endif // HAVE_BAGL_GLYPH_BADGE_ERROR_BLUE + {BAGL_GLYPH_BADGE_ERROR_BLUE, 50, 50, 2, C_badge_error_colors, C_badge_error_bitmap }, +#endif // HAVE_BAGL_GLYPH_BADGE_ERROR_BLUE #ifdef HAVE_BAGL_GLYPH_BADGE_CRITICAL_BLUE - {BAGL_GLYPH_BADGE_CRITICAL_BLUE, 50, 50, 2, C_badge_critical_colors, C_badge_critical_bitmap}, -#endif // HAVE_BAGL_GLYPH_BADGE_CRITICAL_BLUE + {BAGL_GLYPH_BADGE_CRITICAL_BLUE, 50, 50, 2, C_badge_critical_colors, C_badge_critical_bitmap }, +#endif // HAVE_BAGL_GLYPH_BADGE_CRITICAL_BLUE #ifdef HAVE_BAGL_GLYPH_BADGE_ASSISTANCE_BLUE - {BAGL_GLYPH_BADGE_ASSISTANCE_BLUE, 50, 50, 2, C_badge_assistance_colors, C_badge_assistance_bitmap}, -#endif // HAVE_BAGL_GLYPH_BADGE_ASSISTANCE_BLUE + {BAGL_GLYPH_BADGE_ASSISTANCE_BLUE, + 50, 50, + 2, C_badge_assistance_colors, + C_badge_assistance_bitmap }, +#endif // HAVE_BAGL_GLYPH_BADGE_ASSISTANCE_BLUE #ifdef HAVE_BAGL_GLYPH_BADGE_LOCK_BLUE - {BAGL_GLYPH_BADGE_LOCK_BLUE, 50, 50, 2, C_badge_lock_blue_colors, C_badge_lock_blue_bitmap}, -#endif // HAVE_BAGL_GLYPH_BADGE_LOCK_BLUE + {BAGL_GLYPH_BADGE_LOCK_BLUE, 50, 50, 2, C_badge_lock_blue_colors, C_badge_lock_blue_bitmap }, +#endif // HAVE_BAGL_GLYPH_BADGE_LOCK_BLUE #ifdef HAVE_BAGL_GLYPH_ICON_CHECKMARK_BLUE - {BAGL_GLYPH_ICON_CHECKMARK_BLUE, 12, 12, 2, C_icon_checkmark_colors, C_icon_checkmark_bitmap}, -#endif // HAVE_BAGL_GLYPH_ICON_CHECKMARK_BLUE + {BAGL_GLYPH_ICON_CHECKMARK_BLUE, 12, 12, 2, C_icon_checkmark_colors, C_icon_checkmark_bitmap }, +#endif // HAVE_BAGL_GLYPH_ICON_CHECKMARK_BLUE #ifdef HAVE_BAGL_GLYPH_APP_FIRMWARE_BLUE - {BAGL_GLYPH_APP_FIRMWARE_BLUE, 50, 50, 4, C_app_firmware_colors, C_app_firmware_bitmap}, -#endif // HAVE_BAGL_GLYPH_APP_FIRMWARE_BLUE + {BAGL_GLYPH_APP_FIRMWARE_BLUE, 50, 50, 4, C_app_firmware_colors, C_app_firmware_bitmap }, +#endif // HAVE_BAGL_GLYPH_APP_FIRMWARE_BLUE #ifdef HAVE_BAGL_GLYPH_BADGE_BLUE - {BAGL_GLYPH_BADGE_BLUE, 50, 50, 2, C_badge_blue_colors, C_badge_blue_bitmap}, -#endif // HAVE_BAGL_GLYPH_BADGE_BLUE + {BAGL_GLYPH_BADGE_BLUE, 50, 50, 2, C_badge_blue_colors, C_badge_blue_bitmap }, +#endif // HAVE_BAGL_GLYPH_BADGE_BLUE #ifdef HAVE_BAGL_GLYPH_ICON_BRIGHTNESS_HIGH_BLUE - {BAGL_GLYPH_ICON_BRIGHTNESS_HIGH_BLUE, 18, 18, 2, C_icon_brightness_high_colors, C_icon_brightness_high_bitmap}, -#endif // HAVE_BAGL_GLYPH_ICON_BRIGHTNESS_HIGH_BLUE + {BAGL_GLYPH_ICON_BRIGHTNESS_HIGH_BLUE, + 18, 18, + 2, C_icon_brightness_high_colors, + C_icon_brightness_high_bitmap }, +#endif // HAVE_BAGL_GLYPH_ICON_BRIGHTNESS_HIGH_BLUE #ifdef HAVE_BAGL_GLYPH_ICON_BRIGHTNESS_LOW_BLUE - {BAGL_GLYPH_ICON_BRIGHTNESS_LOW_BLUE, 18, 18, 2, C_icon_brightness_low_colors, C_icon_brightness_low_bitmap}, -#endif // HAVE_BAGL_GLYPH_ICON_BRIGHTNESS_LOW_BLUE - - + {BAGL_GLYPH_ICON_BRIGHTNESS_LOW_BLUE, + 18, 18, + 2, C_icon_brightness_low_colors, + C_icon_brightness_low_bitmap }, +#endif // HAVE_BAGL_GLYPH_ICON_BRIGHTNESS_LOW_BLUE }; -const unsigned int C_glyph_count = sizeof(C_glyph_array)/sizeof(C_glyph_array[0]); +const unsigned int C_glyph_count = sizeof(C_glyph_array) / sizeof(C_glyph_array[0]); -#endif // HAVE_BAGL_GLYPH_ARRAY +#endif // HAVE_BAGL_GLYPH_ARRAY diff --git a/lib_blewbxx_impl/include/ledger_ble.h b/lib_blewbxx_impl/include/ledger_ble.h index 4b7ba2c29..4183a7a65 100644 --- a/lib_blewbxx_impl/include/ledger_ble.h +++ b/lib_blewbxx_impl/include/ledger_ble.h @@ -1,20 +1,20 @@ /******************************************************************************* -* Ledger Nano S - Secure firmware -* (c) 2022 Ledger -* -* Licensed under the Apache License, Version 2.0 (the "License"); -* you may not use this file except in compliance with the License. -* You may obtain a copy of the License at -* -* http://www.apache.org/licenses/LICENSE-2.0 -* -* Unless required by applicable law or agreed to in writing, software -* distributed under the License is distributed on an "AS IS" BASIS, -* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -* See the License for the specific language governing permissions and -* limitations under the License. -********************************************************************************/ + * Ledger Nano S - Secure firmware + * (c) 2022 Ledger + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + ********************************************************************************/ #pragma once @@ -35,20 +35,21 @@ /* Exported functions prototypes--------------------------------------------- */ void LEDGER_BLE_init(void); -void LEDGER_BLE_send(uint8_t* packet, uint16_t packet_length); +void LEDGER_BLE_send(uint8_t *packet, uint16_t packet_length); void LEDGER_BLE_receive(void); void LEDGER_BLE_enable_advertising(uint8_t enable); void LEDGER_BLE_reset_pairings(void); -#define LEDGER_BLE_get_mac_address(address) { \ - unsigned char se_serial[8] = {0}; \ - os_serial(se_serial, sizeof(se_serial)); \ - unsigned int uid = cx_crc16(se_serial, 4); \ - address[0] = uid; \ - address[1] = uid>>8; \ - uid = cx_crc16(se_serial+4, 4); \ - address[2] = uid; \ - address[3] = uid>>8; \ - address[4] = 0xF1; \ - address[5] = 0xDE; \ -} +#define LEDGER_BLE_get_mac_address(address) \ + { \ + unsigned char se_serial[8] = {0}; \ + os_serial(se_serial, sizeof(se_serial)); \ + unsigned int uid = cx_crc16(se_serial, 4); \ + address[0] = uid; \ + address[1] = uid >> 8; \ + uid = cx_crc16(se_serial + 4, 4); \ + address[2] = uid; \ + address[3] = uid >> 8; \ + address[4] = 0xF1; \ + address[5] = 0xDE; \ + } diff --git a/lib_blewbxx_impl/src/ledger_ble.c b/lib_blewbxx_impl/src/ledger_ble.c index 696ea4296..4eba98fba 100644 --- a/lib_blewbxx_impl/src/ledger_ble.c +++ b/lib_blewbxx_impl/src/ledger_ble.c @@ -1,20 +1,20 @@ /******************************************************************************* -* Ledger Nano S - Secure firmware -* (c) 2022 Ledger -* -* Licensed under the Apache License, Version 2.0 (the "License"); -* you may not use this file except in compliance with the License. -* You may obtain a copy of the License at -* -* http://www.apache.org/licenses/LICENSE-2.0 -* -* Unless required by applicable law or agreed to in writing, software -* distributed under the License is distributed on an "AS IS" BASIS, -* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -* See the License for the specific language governing permissions and -* limitations under the License. -********************************************************************************/ + * Ledger Nano S - Secure firmware + * (c) 2022 Ledger + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT 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 "os.h" @@ -35,108 +35,107 @@ /* Private enumerations ------------------------------------------------------*/ typedef enum { - BLE_STATE_INITIALIZING, - BLE_STATE_INITIALIZED, - BLE_STATE_CONFIGURE_ADVERTISING, - BLE_STATE_CONNECTING, - BLE_STATE_CONNECTED, - BLE_STATE_DISCONNECTING, + BLE_STATE_INITIALIZING, + BLE_STATE_INITIALIZED, + BLE_STATE_CONFIGURE_ADVERTISING, + BLE_STATE_CONNECTING, + BLE_STATE_CONNECTED, + BLE_STATE_DISCONNECTING, } ble_state_t; - typedef enum { - BLE_INIT_STEP_IDLE, - BLE_INIT_STEP_RESET, - BLE_INIT_STEP_STATIC_ADDRESS, - BLE_INIT_STEP_GATT_INIT, - BLE_INIT_STEP_GAP_INIT, - BLE_INIT_STEP_SET_IO_CAPABILITIES, - BLE_INIT_STEP_SET_AUTH_REQUIREMENTS, - BLE_INIT_STEP_ADD_SERVICE, - BLE_INIT_STEP_ADD_NOTIFICATION_CHARACTERISTIC, - BLE_INIT_STEP_ADD_WRITE_CHARACTERISTIC, - BLE_INIT_STEP_ADD_WRITE_COMMAND_CHARACTERISTIC, - BLE_INIT_STEP_SET_TX_POWER_LEVEL, - BLE_INIT_STEP_CONFIGURE_ADVERTISING, - BLE_INIT_STEP_END, + BLE_INIT_STEP_IDLE, + BLE_INIT_STEP_RESET, + BLE_INIT_STEP_STATIC_ADDRESS, + BLE_INIT_STEP_GATT_INIT, + BLE_INIT_STEP_GAP_INIT, + BLE_INIT_STEP_SET_IO_CAPABILITIES, + BLE_INIT_STEP_SET_AUTH_REQUIREMENTS, + BLE_INIT_STEP_ADD_SERVICE, + BLE_INIT_STEP_ADD_NOTIFICATION_CHARACTERISTIC, + BLE_INIT_STEP_ADD_WRITE_CHARACTERISTIC, + BLE_INIT_STEP_ADD_WRITE_COMMAND_CHARACTERISTIC, + BLE_INIT_STEP_SET_TX_POWER_LEVEL, + BLE_INIT_STEP_CONFIGURE_ADVERTISING, + BLE_INIT_STEP_END, } ble_init_step_t; typedef enum { - BLE_CONFIG_ADV_STEP_IDLE, - BLE_CONFIG_ADV_STEP_SET_ADV_DATAS, - BLE_CONFIG_ADV_STEP_SET_SCAN_RSP_DATAS, - BLE_CONFIG_ADV_STEP_SET_GAP_DEVICE_NAME, - BLE_CONFIG_ADV_STEP_START, - BLE_CONFIG_ADV_STEP_END, + BLE_CONFIG_ADV_STEP_IDLE, + BLE_CONFIG_ADV_STEP_SET_ADV_DATAS, + BLE_CONFIG_ADV_STEP_SET_SCAN_RSP_DATAS, + BLE_CONFIG_ADV_STEP_SET_GAP_DEVICE_NAME, + BLE_CONFIG_ADV_STEP_START, + BLE_CONFIG_ADV_STEP_END, } ble_config_adv_step_t; /* Private types, structures, unions -----------------------------------------*/ typedef struct { - uint16_t connection_handle; - uint8_t role_slave; - uint8_t peer_address_random; - uint8_t peer_address[6]; - uint16_t conn_interval; - uint16_t conn_latency; - uint16_t supervision_timeout; - uint8_t master_clock_accuracy; - uint8_t tx_phy; - uint8_t rx_phy; - uint16_t max_tx_octets; - uint16_t max_tx_time; - uint16_t max_rx_octets; - uint16_t max_rx_time; - uint8_t encrypted; + uint16_t connection_handle; + uint8_t role_slave; + uint8_t peer_address_random; + uint8_t peer_address[6]; + uint16_t conn_interval; + uint16_t conn_latency; + uint16_t supervision_timeout; + uint8_t master_clock_accuracy; + uint8_t tx_phy; + uint8_t rx_phy; + uint16_t max_tx_octets; + uint16_t max_tx_time; + uint16_t max_rx_octets; + uint16_t max_rx_time; + uint8_t encrypted; } ble_connection_t; typedef struct { - // General - ble_state_t state; - char device_name[20+1]; - char device_name_length; - uint8_t random_address[CONFIG_DATA_RANDOM_ADDRESS_LEN]; - - // Init - ble_init_step_t init_step; - - // Advertising configuration - ble_config_adv_step_t adv_step; - uint8_t adv_enable; - - // HCI - uint16_t hci_cmd_opcode; - - // GAP - uint16_t gap_service_handle; - uint16_t gap_device_name_characteristic_handle; - uint16_t gap_appearance_characteristic_handle; - uint8_t advertising_enabled; - ble_connection_t connection; - uint16_t pairing_code; - uint8_t pairing_in_progress; - - // L2CAP - uint8_t connection_updated; - - // ATT/GATT - uint16_t ledger_gatt_service_handle; - uint16_t ledger_gatt_notification_characteristic_handle; - uint16_t ledger_gatt_write_characteristic_handle; - uint16_t ledger_gatt_write_cmd_characteristic_handle; - uint8_t notifications_enabled; - - // PAIRING - uint8_t clear_pairing; - - // APDU - uint8_t wait_write_resp_ack; - uint16_t apdu_buffer_length; - uint8_t apdu_buffer[IO_APDU_BUFFER_SIZE]; - - // TRANSFER MODE - uint8_t transfer_mode_enable; - uint8_t resp_length; - uint8_t resp[2]; + // General + ble_state_t state; + char device_name[20 + 1]; + char device_name_length; + uint8_t random_address[CONFIG_DATA_RANDOM_ADDRESS_LEN]; + + // Init + ble_init_step_t init_step; + + // Advertising configuration + ble_config_adv_step_t adv_step; + uint8_t adv_enable; + + // HCI + uint16_t hci_cmd_opcode; + + // GAP + uint16_t gap_service_handle; + uint16_t gap_device_name_characteristic_handle; + uint16_t gap_appearance_characteristic_handle; + uint8_t advertising_enabled; + ble_connection_t connection; + uint16_t pairing_code; + uint8_t pairing_in_progress; + + // L2CAP + uint8_t connection_updated; + + // ATT/GATT + uint16_t ledger_gatt_service_handle; + uint16_t ledger_gatt_notification_characteristic_handle; + uint16_t ledger_gatt_write_characteristic_handle; + uint16_t ledger_gatt_write_cmd_characteristic_handle; + uint8_t notifications_enabled; + + // PAIRING + uint8_t clear_pairing; + + // APDU + uint8_t wait_write_resp_ack; + uint16_t apdu_buffer_length; + uint8_t apdu_buffer[IO_APDU_BUFFER_SIZE]; + + // TRANSFER MODE + uint8_t transfer_mode_enable; + uint8_t resp_length; + uint8_t resp[2]; } ledger_ble_data_t; @@ -146,14 +145,14 @@ typedef struct { #define BLE_SLAVE_CONN_INTERVAL_MIN 12 // 15ms #define BLE_SLAVE_CONN_INTERVAL_MAX 24 // 30ms -#define BLE_ADVERTISING_INTERVAL_MIN 48 // 30ms -#define BLE_ADVERTISING_INTERVAL_MAX 96 // 60ms +#define BLE_ADVERTISING_INTERVAL_MIN 48 // 30ms +#define BLE_ADVERTISING_INTERVAL_MAX 96 // 60ms #ifdef HAVE_PRINTF #define LOG_BLE PRINTF -#else // !HAVE_PRINTF +#else // !HAVE_PRINTF #define LOG_BLE(...) -#endif // !HAVE_PRINTF +#endif // !HAVE_PRINTF /* Private macros-------------------------------------------------------------*/ @@ -179,6 +178,7 @@ static void check_transfer_mode(uint8_t enable); /* Exported variables --------------------------------------------------------*/ /* Private variables ---------------------------------------------------------*/ +// clang-format off #ifdef TARGET_STAX const uint8_t service_uuid[16] = {0x72,0x65,0x67,0x64,0x65,0x4c,0x00,0x00,0x04,0x60,0x97,0x2C,0x00,0x34,0xD6,0x13,}; const uint8_t charUuidTX[16] = {0x72,0x65,0x67,0x64,0x65,0x4c,0x01,0x00,0x04,0x60,0x97,0x2C,0x00,0x34,0xD6,0x13,}; @@ -192,6 +192,7 @@ const uint8_t charUuidTX[16] = {0x72,0x65,0x67,0x64,0x65,0x4c,0x01,0x00,0x04,0 const uint8_t charUuidRX[16] = {0x72,0x65,0x67,0x64,0x65,0x4c,0x02,0x00,0x04,0x00,0x97,0x2C,0x00,0x34,0xD6,0x13,}; const uint8_t charUuidRX2[16] = {0x72,0x65,0x67,0x64,0x65,0x4c,0x03,0x00,0x04,0x00,0x97,0x2C,0x00,0x34,0xD6,0x13,}; #endif +// clang-format on static ledger_protocol_t ledger_protocol_data; static ledger_ble_data_t ledger_ble_data; @@ -199,1000 +200,975 @@ static ledger_ble_data_t ledger_ble_data; /* Private functions ---------------------------------------------------------*/ static void get_device_name(void) { - memset(ledger_ble_data.device_name, 0, - sizeof(ledger_ble_data.device_name)); - ledger_ble_data.device_name_length = os_setting_get(OS_SETTING_DEVICENAME, - (uint8_t*)ledger_ble_data.device_name, - sizeof(ledger_ble_data.device_name)-1); + memset(ledger_ble_data.device_name, 0, sizeof(ledger_ble_data.device_name)); + ledger_ble_data.device_name_length = os_setting_get(OS_SETTING_DEVICENAME, + (uint8_t *) ledger_ble_data.device_name, + sizeof(ledger_ble_data.device_name) - 1); } static void configure_advertising_mngr(uint16_t opcode) { - if ( (ledger_ble_data.hci_cmd_opcode != 0xFFFF) - &&(opcode != ledger_ble_data.hci_cmd_opcode) - ) { - // Unexpected event => BLE_TODO - return; - } - - uint8_t buffer[31]; - uint8_t index = 0; - - if (ledger_ble_data.adv_step == BLE_CONFIG_ADV_STEP_IDLE) { - ledger_ble_data.connection.connection_handle = 0xFFFF; - ledger_ble_data.advertising_enabled = 0; - LOG_BLE("CONFIGURE ADVERTISING START\n"); - } - else if (ledger_ble_data.adv_step == (BLE_CONFIG_ADV_STEP_END-1)) { - ledger_ble_data.advertising_enabled = 1; - } - - ledger_ble_data.adv_step++; - if ( (ledger_ble_data.adv_step == (BLE_CONFIG_ADV_STEP_END-1)) - &&(!ledger_ble_data.adv_enable) - ) { - ledger_ble_data.adv_step++; - } - - switch (ledger_ble_data.adv_step) { - - case BLE_CONFIG_ADV_STEP_SET_ADV_DATAS: - // Flags - buffer[index++] = 2; - buffer[index++] = AD_TYPE_FLAGS; - buffer[index++] = FLAG_BIT_BR_EDR_NOT_SUPPORTED | FLAG_BIT_LE_GENERAL_DISCOVERABLE_MODE; - - // Complete Local Name - get_device_name(); - buffer[index++] = ledger_ble_data.device_name_length+1; - buffer[index++] = AD_TYPE_COMPLETE_LOCAL_NAME; - memcpy(&buffer[index], ledger_ble_data.device_name, ledger_ble_data.device_name_length); - index += ledger_ble_data.device_name_length; - - ledger_ble_data.hci_cmd_opcode = 0xfc8e; - aci_gap_update_adv_data(index, buffer); - break; - - case BLE_CONFIG_ADV_STEP_SET_SCAN_RSP_DATAS: - // Incomplete List of 128-bit Service UUIDs - buffer[index++] = sizeof(service_uuid)+1; - buffer[index++] = AD_TYPE_128_BIT_SERV_UUID; - memcpy(&buffer[index], service_uuid, sizeof(service_uuid)); - index += sizeof(service_uuid); - - // Slave Connection Interval Range - buffer[index++] = 5; - buffer[index++] = AD_TYPE_SLAVE_CONN_INTERVAL; - buffer[index++] = BLE_SLAVE_CONN_INTERVAL_MIN; - buffer[index++] = 0; - buffer[index++] = BLE_SLAVE_CONN_INTERVAL_MAX; - buffer[index++] = 0; - - ledger_ble_data.hci_cmd_opcode = 0x2009; - hci_le_set_scan_response_data(index, buffer); - break; - - case BLE_CONFIG_ADV_STEP_SET_GAP_DEVICE_NAME: - ledger_ble_data.hci_cmd_opcode = 0xfd06; - aci_gatt_update_char_value(ledger_ble_data.gap_service_handle, - ledger_ble_data.gap_device_name_characteristic_handle, - 0, - ledger_ble_data.device_name_length, - (uint8_t*)ledger_ble_data.device_name); - break; - - case BLE_CONFIG_ADV_STEP_START: - ledger_ble_data.hci_cmd_opcode = 0xfc83; - advertising_enable(1); - break; - - default: - LOG_BLE("CONFIGURE ADVERTISING END\n"); - if (ledger_ble_data.state == BLE_STATE_CONFIGURE_ADVERTISING) { - ledger_ble_data.state = BLE_STATE_INITIALIZED; - } - break; - } + if ((ledger_ble_data.hci_cmd_opcode != 0xFFFF) && (opcode != ledger_ble_data.hci_cmd_opcode)) { + // Unexpected event => BLE_TODO + return; + } + + uint8_t buffer[31]; + uint8_t index = 0; + + if (ledger_ble_data.adv_step == BLE_CONFIG_ADV_STEP_IDLE) { + ledger_ble_data.connection.connection_handle = 0xFFFF; + ledger_ble_data.advertising_enabled = 0; + LOG_BLE("CONFIGURE ADVERTISING START\n"); + } + else if (ledger_ble_data.adv_step == (BLE_CONFIG_ADV_STEP_END - 1)) { + ledger_ble_data.advertising_enabled = 1; + } + + ledger_ble_data.adv_step++; + if ((ledger_ble_data.adv_step == (BLE_CONFIG_ADV_STEP_END - 1)) + && (!ledger_ble_data.adv_enable)) { + ledger_ble_data.adv_step++; + } + + switch (ledger_ble_data.adv_step) { + case BLE_CONFIG_ADV_STEP_SET_ADV_DATAS: + // Flags + buffer[index++] = 2; + buffer[index++] = AD_TYPE_FLAGS; + buffer[index++] = FLAG_BIT_BR_EDR_NOT_SUPPORTED | FLAG_BIT_LE_GENERAL_DISCOVERABLE_MODE; + + // Complete Local Name + get_device_name(); + buffer[index++] = ledger_ble_data.device_name_length + 1; + buffer[index++] = AD_TYPE_COMPLETE_LOCAL_NAME; + memcpy(&buffer[index], ledger_ble_data.device_name, ledger_ble_data.device_name_length); + index += ledger_ble_data.device_name_length; + + ledger_ble_data.hci_cmd_opcode = 0xfc8e; + aci_gap_update_adv_data(index, buffer); + break; + + case BLE_CONFIG_ADV_STEP_SET_SCAN_RSP_DATAS: + // Incomplete List of 128-bit Service UUIDs + buffer[index++] = sizeof(service_uuid) + 1; + buffer[index++] = AD_TYPE_128_BIT_SERV_UUID; + memcpy(&buffer[index], service_uuid, sizeof(service_uuid)); + index += sizeof(service_uuid); + + // Slave Connection Interval Range + buffer[index++] = 5; + buffer[index++] = AD_TYPE_SLAVE_CONN_INTERVAL; + buffer[index++] = BLE_SLAVE_CONN_INTERVAL_MIN; + buffer[index++] = 0; + buffer[index++] = BLE_SLAVE_CONN_INTERVAL_MAX; + buffer[index++] = 0; + + ledger_ble_data.hci_cmd_opcode = 0x2009; + hci_le_set_scan_response_data(index, buffer); + break; + + case BLE_CONFIG_ADV_STEP_SET_GAP_DEVICE_NAME: + ledger_ble_data.hci_cmd_opcode = 0xfd06; + aci_gatt_update_char_value(ledger_ble_data.gap_service_handle, + ledger_ble_data.gap_device_name_characteristic_handle, + 0, + ledger_ble_data.device_name_length, + (uint8_t *) ledger_ble_data.device_name); + break; + + case BLE_CONFIG_ADV_STEP_START: + ledger_ble_data.hci_cmd_opcode = 0xfc83; + advertising_enable(1); + break; + + default: + LOG_BLE("CONFIGURE ADVERTISING END\n"); + if (ledger_ble_data.state == BLE_STATE_CONFIGURE_ADVERTISING) { + ledger_ble_data.state = BLE_STATE_INITIALIZED; + } + break; + } } static void init_mngr(uint16_t opcode, uint8_t *buffer, uint16_t length) { - UNUSED(length); - - if ( (ledger_ble_data.hci_cmd_opcode != 0xFFFF) - &&(opcode != ledger_ble_data.hci_cmd_opcode) - ) { - // Unexpected event => BLE_TODO - return; - } - - if (ledger_ble_data.init_step == BLE_INIT_STEP_IDLE) { - LOG_BLE("INIT START\n"); - } - else if ( (length >= 6) - &&(ledger_ble_data.init_step == BLE_INIT_STEP_GAP_INIT) - ) { - ledger_ble_data.gap_service_handle = U2LE(buffer, 1); - ledger_ble_data.gap_device_name_characteristic_handle = U2LE(buffer, 3); - ledger_ble_data.gap_appearance_characteristic_handle = U2LE(buffer, 5); - } - else if ( (length >= 2) - &&(ledger_ble_data.init_step == BLE_INIT_STEP_ADD_SERVICE) - ) { - ledger_ble_data.ledger_gatt_service_handle = U2LE(buffer, 1); - } - else if ( (length >= 2) - &&(ledger_ble_data.init_step == BLE_INIT_STEP_ADD_NOTIFICATION_CHARACTERISTIC) - ) { - ledger_ble_data.ledger_gatt_notification_characteristic_handle = U2LE(buffer, 1); - } - else if ( (length >= 2) - &&(ledger_ble_data.init_step == BLE_INIT_STEP_ADD_WRITE_CHARACTERISTIC) - ) { - ledger_ble_data.ledger_gatt_write_characteristic_handle = U2LE(buffer, 1); - } - else if ( (length >= 2) - &&(ledger_ble_data.init_step == BLE_INIT_STEP_ADD_WRITE_COMMAND_CHARACTERISTIC) - ) { - ledger_ble_data.ledger_gatt_write_cmd_characteristic_handle = U2LE(buffer, 1); - } - else if (ledger_ble_data.init_step == BLE_INIT_STEP_CONFIGURE_ADVERTISING) { - ledger_ble_data.adv_enable = !os_setting_get(OS_SETTING_PLANEMODE, NULL, 0); - configure_advertising_mngr(opcode); - if (ledger_ble_data.adv_step != BLE_CONFIG_ADV_STEP_END) { - return; - } - } - - ledger_ble_data.init_step++; - - switch (ledger_ble_data.init_step) { - - case BLE_INIT_STEP_RESET: - hci_reset(); - break; - - case BLE_INIT_STEP_STATIC_ADDRESS: - ledger_ble_data.hci_cmd_opcode = 0xfc0c; - aci_hal_write_config_data(CONFIG_DATA_RANDOM_ADDRESS_OFFSET, - CONFIG_DATA_RANDOM_ADDRESS_LEN, - ledger_ble_data.random_address); - break; - - case BLE_INIT_STEP_GATT_INIT: - ledger_ble_data.hci_cmd_opcode = 0xfd01; - aci_gatt_init(); - break; - - case BLE_INIT_STEP_GAP_INIT: - ledger_ble_data.hci_cmd_opcode = 0xfc8a; - aci_gap_init(GAP_PERIPHERAL_ROLE, - PRIVACY_DISABLED, - sizeof(ledger_ble_data.device_name)-1, - &ledger_ble_data.gap_service_handle, - &ledger_ble_data.gap_device_name_characteristic_handle, - &ledger_ble_data.gap_appearance_characteristic_handle); - break; - - case BLE_INIT_STEP_SET_IO_CAPABILITIES: - ledger_ble_data.hci_cmd_opcode = 0xfc85; - aci_gap_set_io_capability(IO_CAP_DISPLAY_YES_NO); - break; - - case BLE_INIT_STEP_SET_AUTH_REQUIREMENTS: - ledger_ble_data.hci_cmd_opcode = 0xfc86; - aci_gap_set_authentication_requirement(BONDING, - MITM_PROTECTION_REQUIRED, - 0x01, // LE Secure connections pairing supported but optional - KEYPRESS_NOT_SUPPORTED, - MIN_ENCRY_KEY_SIZE+1, - MAX_ENCRY_KEY_SIZE, - DONOT_USE_FIXED_PIN_FOR_PAIRING, 0, - STATIC_RANDOM_ADDR); - break; - - case BLE_INIT_STEP_ADD_SERVICE: - ledger_ble_data.hci_cmd_opcode = 0xfd02; - aci_gatt_add_service(UUID_TYPE_128, - (const Service_UUID_t *) service_uuid, - PRIMARY_SERVICE, - 9, - &ledger_ble_data.ledger_gatt_service_handle); - break; - - case BLE_INIT_STEP_ADD_NOTIFICATION_CHARACTERISTIC: - ledger_ble_data.hci_cmd_opcode = 0xfd04; - aci_gatt_add_char(ledger_ble_data.ledger_gatt_service_handle, - UUID_TYPE_128, - (const Char_UUID_t *) charUuidTX, - MAX_MTU_SIZE, - CHAR_PROP_NOTIFY, - ATTR_PERMISSION_AUTHEN_WRITE, - GATT_DONT_NOTIFY_EVENTS, - MAX_ENCRY_KEY_SIZE, - CHAR_VALUE_LEN_VARIABLE, - &ledger_ble_data.ledger_gatt_notification_characteristic_handle); - break; - - case BLE_INIT_STEP_ADD_WRITE_CHARACTERISTIC: - ledger_ble_data.hci_cmd_opcode = 0xfd04; - aci_gatt_add_char(ledger_ble_data.ledger_gatt_service_handle, - UUID_TYPE_128, - (const Char_UUID_t *) charUuidRX, - MAX_MTU_SIZE, - CHAR_PROP_WRITE, - ATTR_PERMISSION_AUTHEN_WRITE, - GATT_NOTIFY_WRITE_REQ_AND_WAIT_FOR_APPL_RESP, - MAX_ENCRY_KEY_SIZE, - CHAR_VALUE_LEN_VARIABLE, - &ledger_ble_data.ledger_gatt_write_characteristic_handle); - break; - - case BLE_INIT_STEP_ADD_WRITE_COMMAND_CHARACTERISTIC: - ledger_ble_data.hci_cmd_opcode = 0xfd04; - aci_gatt_add_char(ledger_ble_data.ledger_gatt_service_handle, - UUID_TYPE_128, - (const Char_UUID_t*)charUuidRX2, - MAX_MTU_SIZE, - CHAR_PROP_WRITE_WITHOUT_RESP, - ATTR_PERMISSION_AUTHEN_WRITE, - GATT_NOTIFY_ATTRIBUTE_WRITE, - MAX_ENCRY_KEY_SIZE, - CHAR_VALUE_LEN_VARIABLE, - &ledger_ble_data.ledger_gatt_write_cmd_characteristic_handle); - break; - - case BLE_INIT_STEP_SET_TX_POWER_LEVEL: - ledger_ble_data.hci_cmd_opcode = 0xfc0f; - aci_hal_set_tx_power_level(1, // High power (ignored) + UNUSED(length); + + if ((ledger_ble_data.hci_cmd_opcode != 0xFFFF) && (opcode != ledger_ble_data.hci_cmd_opcode)) { + // Unexpected event => BLE_TODO + return; + } + + if (ledger_ble_data.init_step == BLE_INIT_STEP_IDLE) { + LOG_BLE("INIT START\n"); + } + else if ((length >= 6) && (ledger_ble_data.init_step == BLE_INIT_STEP_GAP_INIT)) { + ledger_ble_data.gap_service_handle = U2LE(buffer, 1); + ledger_ble_data.gap_device_name_characteristic_handle = U2LE(buffer, 3); + ledger_ble_data.gap_appearance_characteristic_handle = U2LE(buffer, 5); + } + else if ((length >= 2) && (ledger_ble_data.init_step == BLE_INIT_STEP_ADD_SERVICE)) { + ledger_ble_data.ledger_gatt_service_handle = U2LE(buffer, 1); + } + else if ((length >= 2) + && (ledger_ble_data.init_step == BLE_INIT_STEP_ADD_NOTIFICATION_CHARACTERISTIC)) { + ledger_ble_data.ledger_gatt_notification_characteristic_handle = U2LE(buffer, 1); + } + else if ((length >= 2) + && (ledger_ble_data.init_step == BLE_INIT_STEP_ADD_WRITE_CHARACTERISTIC)) { + ledger_ble_data.ledger_gatt_write_characteristic_handle = U2LE(buffer, 1); + } + else if ((length >= 2) + && (ledger_ble_data.init_step == BLE_INIT_STEP_ADD_WRITE_COMMAND_CHARACTERISTIC)) { + ledger_ble_data.ledger_gatt_write_cmd_characteristic_handle = U2LE(buffer, 1); + } + else if (ledger_ble_data.init_step == BLE_INIT_STEP_CONFIGURE_ADVERTISING) { + ledger_ble_data.adv_enable = !os_setting_get(OS_SETTING_PLANEMODE, NULL, 0); + configure_advertising_mngr(opcode); + if (ledger_ble_data.adv_step != BLE_CONFIG_ADV_STEP_END) { + return; + } + } + + ledger_ble_data.init_step++; + + switch (ledger_ble_data.init_step) { + case BLE_INIT_STEP_RESET: + hci_reset(); + break; + + case BLE_INIT_STEP_STATIC_ADDRESS: + ledger_ble_data.hci_cmd_opcode = 0xfc0c; + aci_hal_write_config_data(CONFIG_DATA_RANDOM_ADDRESS_OFFSET, + CONFIG_DATA_RANDOM_ADDRESS_LEN, + ledger_ble_data.random_address); + break; + + case BLE_INIT_STEP_GATT_INIT: + ledger_ble_data.hci_cmd_opcode = 0xfd01; + aci_gatt_init(); + break; + + case BLE_INIT_STEP_GAP_INIT: + ledger_ble_data.hci_cmd_opcode = 0xfc8a; + aci_gap_init(GAP_PERIPHERAL_ROLE, + PRIVACY_DISABLED, + sizeof(ledger_ble_data.device_name) - 1, + &ledger_ble_data.gap_service_handle, + &ledger_ble_data.gap_device_name_characteristic_handle, + &ledger_ble_data.gap_appearance_characteristic_handle); + break; + + case BLE_INIT_STEP_SET_IO_CAPABILITIES: + ledger_ble_data.hci_cmd_opcode = 0xfc85; + aci_gap_set_io_capability(IO_CAP_DISPLAY_YES_NO); + break; + + case BLE_INIT_STEP_SET_AUTH_REQUIREMENTS: + ledger_ble_data.hci_cmd_opcode = 0xfc86; + aci_gap_set_authentication_requirement( + BONDING, + MITM_PROTECTION_REQUIRED, + 0x01, // LE Secure connections pairing supported but optional + KEYPRESS_NOT_SUPPORTED, + MIN_ENCRY_KEY_SIZE + 1, + MAX_ENCRY_KEY_SIZE, + DONOT_USE_FIXED_PIN_FOR_PAIRING, + 0, + STATIC_RANDOM_ADDR); + break; + + case BLE_INIT_STEP_ADD_SERVICE: + ledger_ble_data.hci_cmd_opcode = 0xfd02; + aci_gatt_add_service(UUID_TYPE_128, + (const Service_UUID_t *) service_uuid, + PRIMARY_SERVICE, + 9, + &ledger_ble_data.ledger_gatt_service_handle); + break; + + case BLE_INIT_STEP_ADD_NOTIFICATION_CHARACTERISTIC: + ledger_ble_data.hci_cmd_opcode = 0xfd04; + aci_gatt_add_char(ledger_ble_data.ledger_gatt_service_handle, + UUID_TYPE_128, + (const Char_UUID_t *) charUuidTX, + MAX_MTU_SIZE, + CHAR_PROP_NOTIFY, + ATTR_PERMISSION_AUTHEN_WRITE, + GATT_DONT_NOTIFY_EVENTS, + MAX_ENCRY_KEY_SIZE, + CHAR_VALUE_LEN_VARIABLE, + &ledger_ble_data.ledger_gatt_notification_characteristic_handle); + break; + + case BLE_INIT_STEP_ADD_WRITE_CHARACTERISTIC: + ledger_ble_data.hci_cmd_opcode = 0xfd04; + aci_gatt_add_char(ledger_ble_data.ledger_gatt_service_handle, + UUID_TYPE_128, + (const Char_UUID_t *) charUuidRX, + MAX_MTU_SIZE, + CHAR_PROP_WRITE, + ATTR_PERMISSION_AUTHEN_WRITE, + GATT_NOTIFY_WRITE_REQ_AND_WAIT_FOR_APPL_RESP, + MAX_ENCRY_KEY_SIZE, + CHAR_VALUE_LEN_VARIABLE, + &ledger_ble_data.ledger_gatt_write_characteristic_handle); + break; + + case BLE_INIT_STEP_ADD_WRITE_COMMAND_CHARACTERISTIC: + ledger_ble_data.hci_cmd_opcode = 0xfd04; + aci_gatt_add_char(ledger_ble_data.ledger_gatt_service_handle, + UUID_TYPE_128, + (const Char_UUID_t *) charUuidRX2, + MAX_MTU_SIZE, + CHAR_PROP_WRITE_WITHOUT_RESP, + ATTR_PERMISSION_AUTHEN_WRITE, + GATT_NOTIFY_ATTRIBUTE_WRITE, + MAX_ENCRY_KEY_SIZE, + CHAR_VALUE_LEN_VARIABLE, + &ledger_ble_data.ledger_gatt_write_cmd_characteristic_handle); + break; + + case BLE_INIT_STEP_SET_TX_POWER_LEVEL: + ledger_ble_data.hci_cmd_opcode = 0xfc0f; + aci_hal_set_tx_power_level(1, // High power (ignored) #ifdef TARGET_STAX - 0x19); // 0 dBm -#else // !TARGET_STAX - 0x07); // -14.1 dBm -#endif // !TARGET_STAX - break; - - case BLE_INIT_STEP_CONFIGURE_ADVERTISING: - ledger_ble_data.hci_cmd_opcode = 0xFFFF; - ledger_ble_data.adv_step = BLE_CONFIG_ADV_STEP_IDLE; - ledger_ble_data.adv_enable = !os_setting_get(OS_SETTING_PLANEMODE, NULL, 0); - configure_advertising_mngr(0); - break; - - case BLE_INIT_STEP_END: - LOG_BLE("INIT END\n"); - if (ledger_ble_data.clear_pairing == 0xC1) { - ledger_ble_data.clear_pairing = 0; - aci_gap_clear_security_db(); - } - G_io_app.ble_ready = 1; - ledger_ble_data.state = BLE_STATE_INITIALIZED; - break; - - default: - break; - } + 0x19); // 0 dBm +#else // !TARGET_STAX + 0x07); // -14.1 dBm +#endif // !TARGET_STAX + break; + + case BLE_INIT_STEP_CONFIGURE_ADVERTISING: + ledger_ble_data.hci_cmd_opcode = 0xFFFF; + ledger_ble_data.adv_step = BLE_CONFIG_ADV_STEP_IDLE; + ledger_ble_data.adv_enable = !os_setting_get(OS_SETTING_PLANEMODE, NULL, 0); + configure_advertising_mngr(0); + break; + + case BLE_INIT_STEP_END: + LOG_BLE("INIT END\n"); + if (ledger_ble_data.clear_pairing == 0xC1) { + ledger_ble_data.clear_pairing = 0; + aci_gap_clear_security_db(); + } + G_io_app.ble_ready = 1; + ledger_ble_data.state = BLE_STATE_INITIALIZED; + break; + + default: + break; + } } static void hci_evt_cmd_complete(uint8_t *buffer, uint16_t length) { - if (length < 3) { - return; - } - - uint16_t opcode = U2LE(buffer, 1); - - if (ledger_ble_data.state == BLE_STATE_INITIALIZING) { - init_mngr(opcode, &buffer[3], length); - } - else if (ledger_ble_data.state == BLE_STATE_CONFIGURE_ADVERTISING) { - configure_advertising_mngr(opcode); - } - else if (opcode == 0xfd26) { - // ACI_GATT_WRITE_RESP - if (ledger_ble_data.wait_write_resp_ack != 0) { - ledger_ble_data.wait_write_resp_ack = 0; - if (ledger_protocol_data.tx_chunk_length >= 2) { - G_io_app.ble_xfer_timeout = 2000; - notify_chunk(); - } - } - } - else if (opcode == 0xfd06) { - // ACI_GATT_UPDATE_CHAR_VALUE - ledger_protocol_data.tx_chunk_length = 0; - if (ledger_ble_data.transfer_mode_enable) { - if ( (ledger_protocol_data.rx_apdu_length) - &&(ledger_protocol_data.rx_apdu_status == APDU_STATUS_COMPLETE) - ) { - memcpy(G_io_apdu_buffer, - ledger_protocol_data.rx_apdu_buffer, - ledger_protocol_data.rx_apdu_length); - G_io_app.apdu_length = ledger_protocol_data.rx_apdu_length; - G_io_app.apdu_state = APDU_BLE; - G_io_app.apdu_media = IO_APDU_MEDIA_BLE; - ledger_protocol_data.rx_apdu_length = 0; - } - } - else { - if (ledger_protocol_data.tx_apdu_buffer) { - LEDGER_PROTOCOL_tx(NULL, 0); - notify_chunk(); - } - if (!ledger_protocol_data.tx_apdu_buffer) { - ledger_protocol_data.tx_chunk_length = 0; - G_io_app.ble_xfer_timeout = 0; - G_io_app.apdu_state = APDU_IDLE; - if ( (!ledger_ble_data.connection_updated) - &&(ledger_ble_data.connection.conn_interval > BLE_SLAVE_CONN_INTERVAL_MIN) - ) { - ledger_ble_data.connection_updated = 1; - aci_l2cap_connection_parameter_update_req(ledger_ble_data.connection.connection_handle, - BLE_SLAVE_CONN_INTERVAL_MIN, BLE_SLAVE_CONN_INTERVAL_MIN, - ledger_ble_data.connection.conn_latency, - ledger_ble_data.connection.supervision_timeout); - } - } - } - } - else if ( (opcode == 0xfc81) - ||(opcode == 0xfc83) - ) { - LOG_BLE("HCI_LE_SET_ADVERTISE_ENABLE %04X %d %d\n", ledger_ble_data.connection.connection_handle, - G_io_app.disabling_advertising, - G_io_app.enabling_advertising); - if (ledger_ble_data.connection.connection_handle != 0xFFFF) { - if (G_io_app.disabling_advertising) { - // Connected & ordered to disable ble, force disconnection - end_pairing_ux(BOLOS_UX_ASYNCHMODAL_PAIRING_STATUS_FAILED); - LEDGER_BLE_init(); - } - } - else if (G_io_app.disabling_advertising) { - ledger_ble_data.advertising_enabled = 0; - if (G_io_app.name_changed) { - start_advertising(); - } - } - else if (G_io_app.enabling_advertising) { - ledger_ble_data.advertising_enabled = 1; - } - else { - ledger_ble_data.advertising_enabled = 1; - } - G_io_app.disabling_advertising = 0; - G_io_app.enabling_advertising = 0; - } - else if (opcode == 0xfca5) { - LOG_BLE("ACI_GAP_NUMERIC_COMPARISON_VALUE_CONFIRM_YESNO\n"); - } - else if (opcode == 0xfc94) { - LOG_BLE("ACI_GAP_CLEAR_SECURITY_DB\n"); - } - else if (opcode == 0xfd25) { - LOG_BLE("ACI_GATT_CONFIRM_INDICATION\n"); - } - else { - LOG_BLE("HCI EVT CMD COMPLETE 0x%04X\n", opcode); - } + if (length < 3) { + return; + } + + uint16_t opcode = U2LE(buffer, 1); + + if (ledger_ble_data.state == BLE_STATE_INITIALIZING) { + init_mngr(opcode, &buffer[3], length); + } + else if (ledger_ble_data.state == BLE_STATE_CONFIGURE_ADVERTISING) { + configure_advertising_mngr(opcode); + } + else if (opcode == 0xfd26) { + // ACI_GATT_WRITE_RESP + if (ledger_ble_data.wait_write_resp_ack != 0) { + ledger_ble_data.wait_write_resp_ack = 0; + if (ledger_protocol_data.tx_chunk_length >= 2) { + G_io_app.ble_xfer_timeout = 2000; + notify_chunk(); + } + } + } + else if (opcode == 0xfd06) { + // ACI_GATT_UPDATE_CHAR_VALUE + ledger_protocol_data.tx_chunk_length = 0; + if (ledger_ble_data.transfer_mode_enable) { + if ((ledger_protocol_data.rx_apdu_length) + && (ledger_protocol_data.rx_apdu_status == APDU_STATUS_COMPLETE)) { + memcpy(G_io_apdu_buffer, + ledger_protocol_data.rx_apdu_buffer, + ledger_protocol_data.rx_apdu_length); + G_io_app.apdu_length = ledger_protocol_data.rx_apdu_length; + G_io_app.apdu_state = APDU_BLE; + G_io_app.apdu_media = IO_APDU_MEDIA_BLE; + ledger_protocol_data.rx_apdu_length = 0; + } + } + else { + if (ledger_protocol_data.tx_apdu_buffer) { + LEDGER_PROTOCOL_tx(NULL, 0); + notify_chunk(); + } + if (!ledger_protocol_data.tx_apdu_buffer) { + ledger_protocol_data.tx_chunk_length = 0; + G_io_app.ble_xfer_timeout = 0; + G_io_app.apdu_state = APDU_IDLE; + if ((!ledger_ble_data.connection_updated) + && (ledger_ble_data.connection.conn_interval > BLE_SLAVE_CONN_INTERVAL_MIN)) { + ledger_ble_data.connection_updated = 1; + aci_l2cap_connection_parameter_update_req( + ledger_ble_data.connection.connection_handle, + BLE_SLAVE_CONN_INTERVAL_MIN, + BLE_SLAVE_CONN_INTERVAL_MIN, + ledger_ble_data.connection.conn_latency, + ledger_ble_data.connection.supervision_timeout); + } + } + } + } + else if ((opcode == 0xfc81) || (opcode == 0xfc83)) { + LOG_BLE("HCI_LE_SET_ADVERTISE_ENABLE %04X %d %d\n", + ledger_ble_data.connection.connection_handle, + G_io_app.disabling_advertising, + G_io_app.enabling_advertising); + if (ledger_ble_data.connection.connection_handle != 0xFFFF) { + if (G_io_app.disabling_advertising) { + // Connected & ordered to disable ble, force disconnection + end_pairing_ux(BOLOS_UX_ASYNCHMODAL_PAIRING_STATUS_FAILED); + LEDGER_BLE_init(); + } + } + else if (G_io_app.disabling_advertising) { + ledger_ble_data.advertising_enabled = 0; + if (G_io_app.name_changed) { + start_advertising(); + } + } + else if (G_io_app.enabling_advertising) { + ledger_ble_data.advertising_enabled = 1; + } + else { + ledger_ble_data.advertising_enabled = 1; + } + G_io_app.disabling_advertising = 0; + G_io_app.enabling_advertising = 0; + } + else if (opcode == 0xfca5) { + LOG_BLE("ACI_GAP_NUMERIC_COMPARISON_VALUE_CONFIRM_YESNO\n"); + } + else if (opcode == 0xfc94) { + LOG_BLE("ACI_GAP_CLEAR_SECURITY_DB\n"); + } + else if (opcode == 0xfd25) { + LOG_BLE("ACI_GATT_CONFIRM_INDICATION\n"); + } + else { + LOG_BLE("HCI EVT CMD COMPLETE 0x%04X\n", opcode); + } } static void hci_evt_le_meta_evt(uint8_t *buffer, uint16_t length) { - if (!length) { - return; - } - - switch (buffer[0]) { - - case HCI_LE_CONNECTION_COMPLETE_SUBEVT_CODE: - ledger_ble_data.connection.connection_handle = U2LE(buffer, 2); - ledger_ble_data.connection.role_slave = buffer[4]; - ledger_ble_data.connection.peer_address_random = buffer[5]; - memcpy(ledger_ble_data.connection.peer_address, &buffer[6], 6); - ledger_ble_data.connection.conn_interval = U2LE(buffer, 12); - ledger_ble_data.connection.conn_latency = U2LE(buffer, 14); - ledger_ble_data.connection.supervision_timeout = U2LE(buffer, 16); - ledger_ble_data.connection.master_clock_accuracy = buffer[18]; - ledger_ble_data.connection.encrypted = 0; - ledger_ble_data.transfer_mode_enable = 0; - LOG_BLE("LE CONNECTION COMPLETE %04X - %04X- %04X- %04X\n", ledger_ble_data.connection.connection_handle, - ledger_ble_data.connection.conn_interval, - ledger_ble_data.connection.conn_latency, - ledger_ble_data.connection.supervision_timeout); - ledger_protocol_data.mtu = ATT_MTU-3+2; - ledger_ble_data.notifications_enabled = 0; - ledger_ble_data.advertising_enabled = 0; - ledger_protocol_data.mtu_negotiated = 0; - ledger_ble_data.connection_updated = 0; - break; - - case HCI_LE_CONNECTION_UPDATE_COMPLETE_SUBEVT_CODE: - ledger_ble_data.connection.connection_handle = U2LE(buffer, 2); - ledger_ble_data.connection.conn_interval = U2LE(buffer, 4); - ledger_ble_data.connection.conn_latency = U2LE(buffer, 6); - ledger_ble_data.connection.supervision_timeout = U2LE(buffer, 8); - LOG_BLE("LE CONNECTION UPDATE %04X - %04X- %04X- %04X\n", ledger_ble_data.connection.connection_handle, - ledger_ble_data.connection.conn_interval, - ledger_ble_data.connection.conn_latency, - ledger_ble_data.connection.supervision_timeout); - break; - - case HCI_LE_DATA_LENGTH_CHANGE_SUBEVT_CODE: - if (U2LE(buffer, 1) == ledger_ble_data.connection.connection_handle) { - ledger_ble_data.connection.max_tx_octets = U2LE(buffer, 3); - ledger_ble_data.connection.max_tx_time = U2LE(buffer, 5); - ledger_ble_data.connection.max_rx_octets = U2LE(buffer, 7); - ledger_ble_data.connection.max_rx_time = U2LE(buffer, 9); - LOG_BLE("LE DATA LENGTH CHANGE %04X - %04X- %04X- %04X\n", ledger_ble_data.connection.max_tx_octets, - ledger_ble_data.connection.max_tx_time, - ledger_ble_data.connection.max_rx_octets, - ledger_ble_data.connection.max_rx_time); - } - break; - - case HCI_LE_PHY_UPDATE_COMPLETE_SUBEVT_CODE: - if (U2LE(buffer, 2) == ledger_ble_data.connection.connection_handle) { - ledger_ble_data.connection.tx_phy = buffer[4]; - ledger_ble_data.connection.rx_phy = buffer[5]; - LOG_BLE("LE PHY UPDATE %02X - %02X\n", ledger_ble_data.connection.tx_phy, - ledger_ble_data.connection.rx_phy); - } - break; - - default: - LOG_BLE("HCI LE META 0x%02X\n", buffer[0]); - break; - } + if (!length) { + return; + } + + switch (buffer[0]) { + case HCI_LE_CONNECTION_COMPLETE_SUBEVT_CODE: + ledger_ble_data.connection.connection_handle = U2LE(buffer, 2); + ledger_ble_data.connection.role_slave = buffer[4]; + ledger_ble_data.connection.peer_address_random = buffer[5]; + memcpy(ledger_ble_data.connection.peer_address, &buffer[6], 6); + ledger_ble_data.connection.conn_interval = U2LE(buffer, 12); + ledger_ble_data.connection.conn_latency = U2LE(buffer, 14); + ledger_ble_data.connection.supervision_timeout = U2LE(buffer, 16); + ledger_ble_data.connection.master_clock_accuracy = buffer[18]; + ledger_ble_data.connection.encrypted = 0; + ledger_ble_data.transfer_mode_enable = 0; + LOG_BLE("LE CONNECTION COMPLETE %04X - %04X- %04X- %04X\n", + ledger_ble_data.connection.connection_handle, + ledger_ble_data.connection.conn_interval, + ledger_ble_data.connection.conn_latency, + ledger_ble_data.connection.supervision_timeout); + ledger_protocol_data.mtu = ATT_MTU - 3 + 2; + ledger_ble_data.notifications_enabled = 0; + ledger_ble_data.advertising_enabled = 0; + ledger_protocol_data.mtu_negotiated = 0; + ledger_ble_data.connection_updated = 0; + break; + + case HCI_LE_CONNECTION_UPDATE_COMPLETE_SUBEVT_CODE: + ledger_ble_data.connection.connection_handle = U2LE(buffer, 2); + ledger_ble_data.connection.conn_interval = U2LE(buffer, 4); + ledger_ble_data.connection.conn_latency = U2LE(buffer, 6); + ledger_ble_data.connection.supervision_timeout = U2LE(buffer, 8); + LOG_BLE("LE CONNECTION UPDATE %04X - %04X- %04X- %04X\n", + ledger_ble_data.connection.connection_handle, + ledger_ble_data.connection.conn_interval, + ledger_ble_data.connection.conn_latency, + ledger_ble_data.connection.supervision_timeout); + break; + + case HCI_LE_DATA_LENGTH_CHANGE_SUBEVT_CODE: + if (U2LE(buffer, 1) == ledger_ble_data.connection.connection_handle) { + ledger_ble_data.connection.max_tx_octets = U2LE(buffer, 3); + ledger_ble_data.connection.max_tx_time = U2LE(buffer, 5); + ledger_ble_data.connection.max_rx_octets = U2LE(buffer, 7); + ledger_ble_data.connection.max_rx_time = U2LE(buffer, 9); + LOG_BLE("LE DATA LENGTH CHANGE %04X - %04X- %04X- %04X\n", + ledger_ble_data.connection.max_tx_octets, + ledger_ble_data.connection.max_tx_time, + ledger_ble_data.connection.max_rx_octets, + ledger_ble_data.connection.max_rx_time); + } + break; + + case HCI_LE_PHY_UPDATE_COMPLETE_SUBEVT_CODE: + if (U2LE(buffer, 2) == ledger_ble_data.connection.connection_handle) { + ledger_ble_data.connection.tx_phy = buffer[4]; + ledger_ble_data.connection.rx_phy = buffer[5]; + LOG_BLE("LE PHY UPDATE %02X - %02X\n", + ledger_ble_data.connection.tx_phy, + ledger_ble_data.connection.rx_phy); + } + break; + + default: + LOG_BLE("HCI LE META 0x%02X\n", buffer[0]); + break; + } } static void hci_evt_vendor(uint8_t *buffer, uint16_t length) { - if (length < 4) { - return; - } - - uint16_t opcode = U2LE(buffer, 0); - - if (U2LE(buffer, 2) != ledger_ble_data.connection.connection_handle) { - return; - } - - switch (opcode) { - - case ACI_GAP_PAIRING_COMPLETE_VSEVT_CODE: - LOG_BLE("PAIRING"); - switch (buffer[4]) { - - case SMP_PAIRING_STATUS_SUCCESS: - LOG_BLE(" SUCCESS\n"); - end_pairing_ux(BOLOS_UX_ASYNCHMODAL_PAIRING_STATUS_SUCCESS); - break; - - case SMP_PAIRING_STATUS_SMP_TIMEOUT: - LOG_BLE(" TIMEOUT\n"); - end_pairing_ux(BOLOS_UX_ASYNCHMODAL_PAIRING_STATUS_TIMEOUT); - break; - - case SMP_PAIRING_STATUS_PAIRING_FAILED: - LOG_BLE(" FAILED : %02X\n", buffer[5]); - if (buffer[5] == 0x08) { // UNSPECIFIED_REASON - end_pairing_ux(BOLOS_UX_ASYNCHMODAL_PAIRING_STATUS_CANCELLED_FROM_REMOTE); - } - else { - end_pairing_ux(BOLOS_UX_ASYNCHMODAL_PAIRING_STATUS_FAILED); - } - break; - - default: - end_pairing_ux(BOLOS_UX_ASYNCHMODAL_PAIRING_STATUS_FAILED); - break; - } - ledger_ble_data.pairing_in_progress = 0; - break; - - case ACI_GAP_PASS_KEY_REQ_VSEVT_CODE: - LOG_BLE("PASSKEY REQ\n"); - ask_user_pairing_passkey(); - break; - - case ACI_GAP_NUMERIC_COMPARISON_VALUE_VSEVT_CODE: - LOG_BLE("NUMERIC COMP : %d\n", U4LE(buffer, 4)); - ask_user_pairing_numeric_comparison(U4LE(buffer, 4)); - break; - - case ACI_GATT_ATTRIBUTE_MODIFIED_VSEVT_CODE: - attribute_modified(&buffer[4], length-4); - break; - - case ACI_ATT_EXCHANGE_MTU_RESP_VSEVT_CODE: - ledger_protocol_data.mtu = U2LE(buffer, 4)-3+2; - ledger_protocol_data.mtu_negotiated = 1; - LOG_BLE("MTU : %d\n", U2LE(buffer, 4)); - break; - - case ACI_L2CAP_CONNECTION_UPDATE_RESP_VSEVT_CODE: - LOG_BLE("CONNECTION UPDATE RESP %d\n", buffer[4]); - break; - - case ACI_GATT_WRITE_PERMIT_REQ_VSEVT_CODE: - write_permit_request(&buffer[4], length-4); - break; - - case ACI_GATT_INDICATION_VSEVT_CODE: - LOG_BLE("INDICATION EVT\n"); - aci_gatt_confirm_indication(ledger_ble_data.connection.connection_handle); - break; - - case ACI_GATT_PROC_COMPLETE_VSEVT_CODE: - LOG_BLE("PROCEDURE COMPLETE\n"); - break; - - case ACI_GATT_PROC_TIMEOUT_VSEVT_CODE: - LOG_BLE("PROCEDURE TIMEOUT\n"); - end_pairing_ux(BOLOS_UX_ASYNCHMODAL_PAIRING_STATUS_FAILED); - LEDGER_BLE_init(); - break; - - default: - LOG_BLE("HCI VENDOR 0x%04X\n", opcode); - break; - } + if (length < 4) { + return; + } + + uint16_t opcode = U2LE(buffer, 0); + + if (U2LE(buffer, 2) != ledger_ble_data.connection.connection_handle) { + return; + } + + switch (opcode) { + case ACI_GAP_PAIRING_COMPLETE_VSEVT_CODE: + LOG_BLE("PAIRING"); + switch (buffer[4]) { + case SMP_PAIRING_STATUS_SUCCESS: + LOG_BLE(" SUCCESS\n"); + end_pairing_ux(BOLOS_UX_ASYNCHMODAL_PAIRING_STATUS_SUCCESS); + break; + + case SMP_PAIRING_STATUS_SMP_TIMEOUT: + LOG_BLE(" TIMEOUT\n"); + end_pairing_ux(BOLOS_UX_ASYNCHMODAL_PAIRING_STATUS_TIMEOUT); + break; + + case SMP_PAIRING_STATUS_PAIRING_FAILED: + LOG_BLE(" FAILED : %02X\n", buffer[5]); + if (buffer[5] == 0x08) { // UNSPECIFIED_REASON + end_pairing_ux(BOLOS_UX_ASYNCHMODAL_PAIRING_STATUS_CANCELLED_FROM_REMOTE); + } + else { + end_pairing_ux(BOLOS_UX_ASYNCHMODAL_PAIRING_STATUS_FAILED); + } + break; + + default: + end_pairing_ux(BOLOS_UX_ASYNCHMODAL_PAIRING_STATUS_FAILED); + break; + } + ledger_ble_data.pairing_in_progress = 0; + break; + + case ACI_GAP_PASS_KEY_REQ_VSEVT_CODE: + LOG_BLE("PASSKEY REQ\n"); + ask_user_pairing_passkey(); + break; + + case ACI_GAP_NUMERIC_COMPARISON_VALUE_VSEVT_CODE: + LOG_BLE("NUMERIC COMP : %d\n", U4LE(buffer, 4)); + ask_user_pairing_numeric_comparison(U4LE(buffer, 4)); + break; + + case ACI_GATT_ATTRIBUTE_MODIFIED_VSEVT_CODE: + attribute_modified(&buffer[4], length - 4); + break; + + case ACI_ATT_EXCHANGE_MTU_RESP_VSEVT_CODE: + ledger_protocol_data.mtu = U2LE(buffer, 4) - 3 + 2; + ledger_protocol_data.mtu_negotiated = 1; + LOG_BLE("MTU : %d\n", U2LE(buffer, 4)); + break; + + case ACI_L2CAP_CONNECTION_UPDATE_RESP_VSEVT_CODE: + LOG_BLE("CONNECTION UPDATE RESP %d\n", buffer[4]); + break; + + case ACI_GATT_WRITE_PERMIT_REQ_VSEVT_CODE: + write_permit_request(&buffer[4], length - 4); + break; + + case ACI_GATT_INDICATION_VSEVT_CODE: + LOG_BLE("INDICATION EVT\n"); + aci_gatt_confirm_indication(ledger_ble_data.connection.connection_handle); + break; + + case ACI_GATT_PROC_COMPLETE_VSEVT_CODE: + LOG_BLE("PROCEDURE COMPLETE\n"); + break; + + case ACI_GATT_PROC_TIMEOUT_VSEVT_CODE: + LOG_BLE("PROCEDURE TIMEOUT\n"); + end_pairing_ux(BOLOS_UX_ASYNCHMODAL_PAIRING_STATUS_FAILED); + LEDGER_BLE_init(); + break; + + default: + LOG_BLE("HCI VENDOR 0x%04X\n", opcode); + break; + } } static void end_pairing_ux(uint8_t pairing_ok) { - bolos_ux_params_t ux_params; - - LOG_BLE("end_pairing_ux : %d (%d)\n", pairing_ok, ledger_ble_data.pairing_in_progress); - if (ledger_ble_data.pairing_in_progress) { - ux_params.ux_id = BOLOS_UX_ASYNCHMODAL_PAIRING_CANCEL; - ux_params.u.pairing_status.pairing_ok = pairing_ok; - ux_params.len = sizeof(ux_params.u.pairing_status); - G_io_asynch_ux_callback.asynchmodal_end_callback = NULL; - os_ux(&ux_params); - } + bolos_ux_params_t ux_params; + + LOG_BLE("end_pairing_ux : %d (%d)\n", pairing_ok, ledger_ble_data.pairing_in_progress); + if (ledger_ble_data.pairing_in_progress) { + ux_params.ux_id = BOLOS_UX_ASYNCHMODAL_PAIRING_CANCEL; + ux_params.u.pairing_status.pairing_ok = pairing_ok; + ux_params.len = sizeof(ux_params.u.pairing_status); + G_io_asynch_ux_callback.asynchmodal_end_callback = NULL; + os_ux(&ux_params); + } } static void ask_user_pairing_numeric_comparison(uint32_t code) { - bolos_ux_params_t ux_params; - - ux_params.u.pairing_request.type = BOLOS_UX_ASYNCHMODAL_PAIRING_REQUEST_NUMCOMP; - ux_params.u.pairing_request.pairing_info_len = 6; - SPRINTF(ux_params.u.pairing_request.pairing_info, "%06d", (unsigned int)code); - ux_params.ux_id = BOLOS_UX_ASYNCHMODAL_PAIRING_REQUEST; - ux_params.len = sizeof(ux_params.u.pairing_request); - G_io_asynch_ux_callback.asynchmodal_end_callback = rsp_user_pairing_numeric_comparison; - ledger_ble_data.pairing_in_progress = 1; - os_ux(&ux_params); + bolos_ux_params_t ux_params; + + ux_params.u.pairing_request.type = BOLOS_UX_ASYNCHMODAL_PAIRING_REQUEST_NUMCOMP; + ux_params.u.pairing_request.pairing_info_len = 6; + SPRINTF(ux_params.u.pairing_request.pairing_info, "%06d", (unsigned int) code); + ux_params.ux_id = BOLOS_UX_ASYNCHMODAL_PAIRING_REQUEST; + ux_params.len = sizeof(ux_params.u.pairing_request); + G_io_asynch_ux_callback.asynchmodal_end_callback = rsp_user_pairing_numeric_comparison; + ledger_ble_data.pairing_in_progress = 1; + os_ux(&ux_params); } static void rsp_user_pairing_numeric_comparison(unsigned int status) { - if (status == BOLOS_UX_OK) { - end_pairing_ux(BOLOS_UX_ASYNCHMODAL_PAIRING_STATUS_CONFIRM_CODE_YES); - aci_gap_numeric_comparison_value_confirm_yesno(ledger_ble_data.connection.connection_handle, 1); - } - else if (status == BOLOS_UX_IGNORE) { - ledger_ble_data.pairing_in_progress = 0; - aci_gap_numeric_comparison_value_confirm_yesno(ledger_ble_data.connection.connection_handle, 0); - } - else { - end_pairing_ux(BOLOS_UX_ASYNCHMODAL_PAIRING_STATUS_CONFIRM_CODE_NO); - aci_gap_numeric_comparison_value_confirm_yesno(ledger_ble_data.connection.connection_handle, 0); - } + if (status == BOLOS_UX_OK) { + end_pairing_ux(BOLOS_UX_ASYNCHMODAL_PAIRING_STATUS_CONFIRM_CODE_YES); + aci_gap_numeric_comparison_value_confirm_yesno(ledger_ble_data.connection.connection_handle, + 1); + } + else if (status == BOLOS_UX_IGNORE) { + ledger_ble_data.pairing_in_progress = 0; + aci_gap_numeric_comparison_value_confirm_yesno(ledger_ble_data.connection.connection_handle, + 0); + } + else { + end_pairing_ux(BOLOS_UX_ASYNCHMODAL_PAIRING_STATUS_CONFIRM_CODE_NO); + aci_gap_numeric_comparison_value_confirm_yesno(ledger_ble_data.connection.connection_handle, + 0); + } } static void ask_user_pairing_passkey(void) { - bolos_ux_params_t ux_params; - - ledger_ble_data.pairing_code = cx_rng_u32_range_func(0, 1000000, cx_rng_u32); - ux_params.u.pairing_request.type = BOLOS_UX_ASYNCHMODAL_PAIRING_REQUEST_PASSKEY; - ux_params.u.pairing_request.pairing_info_len = 6; - SPRINTF(ux_params.u.pairing_request.pairing_info, "%06d", ledger_ble_data.pairing_code); - ux_params.ux_id = BOLOS_UX_ASYNCHMODAL_PAIRING_REQUEST; - ux_params.len = sizeof(ux_params.u.pairing_request); - G_io_asynch_ux_callback.asynchmodal_end_callback = rsp_user_pairing_passkey; - ledger_ble_data.pairing_in_progress = 1; - os_ux(&ux_params); + bolos_ux_params_t ux_params; + + ledger_ble_data.pairing_code = cx_rng_u32_range_func(0, 1000000, cx_rng_u32); + ux_params.u.pairing_request.type = BOLOS_UX_ASYNCHMODAL_PAIRING_REQUEST_PASSKEY; + ux_params.u.pairing_request.pairing_info_len = 6; + SPRINTF(ux_params.u.pairing_request.pairing_info, "%06d", ledger_ble_data.pairing_code); + ux_params.ux_id = BOLOS_UX_ASYNCHMODAL_PAIRING_REQUEST; + ux_params.len = sizeof(ux_params.u.pairing_request); + G_io_asynch_ux_callback.asynchmodal_end_callback = rsp_user_pairing_passkey; + ledger_ble_data.pairing_in_progress = 1; + os_ux(&ux_params); } static void rsp_user_pairing_passkey(unsigned int status) { - if (status != BOLOS_UX_OK) { // BLE_TODO - end_pairing_ux(BOLOS_UX_ASYNCHMODAL_PAIRING_STATUS_ACCEPT_PASSKEY); - ledger_ble_data.pairing_code = cx_rng_u32_range_func(0, 1000000, cx_rng_u32); - } - else { - end_pairing_ux(BOLOS_UX_ASYNCHMODAL_PAIRING_STATUS_CANCEL_PASSKEY); - } - aci_gap_pass_key_resp(ledger_ble_data.connection.connection_handle, - ledger_ble_data.pairing_code); + if (status != BOLOS_UX_OK) { // BLE_TODO + end_pairing_ux(BOLOS_UX_ASYNCHMODAL_PAIRING_STATUS_ACCEPT_PASSKEY); + ledger_ble_data.pairing_code = cx_rng_u32_range_func(0, 1000000, cx_rng_u32); + } + else { + end_pairing_ux(BOLOS_UX_ASYNCHMODAL_PAIRING_STATUS_CANCEL_PASSKEY); + } + aci_gap_pass_key_resp(ledger_ble_data.connection.connection_handle, + ledger_ble_data.pairing_code); } static void attribute_modified(uint8_t *buffer, uint16_t length) { - if (length < 6) { - return; - } - - uint16_t att_handle = U2LE(buffer, 0); - uint16_t offset = U2LE(buffer, 2); - uint16_t att_data_length = U2LE(buffer, 4); - - if ( (att_handle == ledger_ble_data.ledger_gatt_notification_characteristic_handle+2) - &&(att_data_length == 2) - &&(offset == 0) - ) { - // Peer device registering/unregistering for notifications - if (U2LE(buffer, 6) != 0) { - LOG_BLE("REGISTERED FOR NOTIFICATIONS\n"); - ledger_ble_data.notifications_enabled = 1; - if (!ledger_protocol_data.mtu_negotiated) { - aci_gatt_exchange_config(ledger_ble_data.connection.connection_handle); - } - } - else { - LOG_BLE("NOT REGISTERED FOR NOTIFICATIONS\n"); - ledger_ble_data.notifications_enabled = 0; - } - } - else if ( (att_handle == ledger_ble_data.ledger_gatt_write_cmd_characteristic_handle+1) - &&(ledger_ble_data.notifications_enabled) - &&(ledger_ble_data.connection.encrypted) - &&(att_data_length) - ) { - LOG_BLE("WRITE CMD %d\n", length-4); - buffer[4] = 0xDE; - buffer[5] = 0xF1; - LEDGER_PROTOCOL_rx(&buffer[4], length-4); - - if (ledger_protocol_data.rx_apdu_status == APDU_STATUS_COMPLETE) { - check_transfer_mode(G_io_app.transfer_mode); - if (ledger_ble_data.transfer_mode_enable) { - if (U2BE(ledger_ble_data.resp, 0) != SWO_SUCCESS) { - LOG_BLE("Transfer failed 0x%04x\n", U2BE(ledger_ble_data.resp, 0)); - G_io_app.transfer_mode = 0; - check_transfer_mode(G_io_app.transfer_mode); - memcpy(G_io_apdu_buffer, - ledger_protocol_data.rx_apdu_buffer, - ledger_protocol_data.rx_apdu_length); - G_io_app.apdu_length = ledger_protocol_data.rx_apdu_length; - G_io_app.apdu_state = APDU_BLE; - ledger_protocol_data.rx_apdu_length = 0; - ledger_protocol_data.rx_apdu_status = APDU_STATUS_WAITING; - G_io_app.apdu_media = IO_APDU_MEDIA_BLE; - } - else if (ledger_ble_data.resp_length) { - LEDGER_PROTOCOL_tx(ledger_ble_data.resp, ledger_ble_data.resp_length); - ledger_ble_data.resp_length = 0; - notify_chunk(); - } - } - else { - memcpy(G_io_apdu_buffer, - ledger_protocol_data.rx_apdu_buffer, - ledger_protocol_data.rx_apdu_length); - G_io_app.apdu_length = ledger_protocol_data.rx_apdu_length; - G_io_app.apdu_state = APDU_BLE; - ledger_protocol_data.rx_apdu_length = 0; - ledger_protocol_data.rx_apdu_status = APDU_STATUS_WAITING; - G_io_app.apdu_media = IO_APDU_MEDIA_BLE; - } - } - else if (ledger_protocol_data.tx_chunk_length >= 2) { - G_io_app.ble_xfer_timeout = 2000; - notify_chunk(); - G_io_app.apdu_state = APDU_BLE; - } - } - else { - LOG_BLE("ATT MODIFIED %04X %d bytes at offset %d\n", att_handle, att_data_length, offset); - } + if (length < 6) { + return; + } + + uint16_t att_handle = U2LE(buffer, 0); + uint16_t offset = U2LE(buffer, 2); + uint16_t att_data_length = U2LE(buffer, 4); + + if ((att_handle == ledger_ble_data.ledger_gatt_notification_characteristic_handle + 2) + && (att_data_length == 2) && (offset == 0)) { + // Peer device registering/unregistering for notifications + if (U2LE(buffer, 6) != 0) { + LOG_BLE("REGISTERED FOR NOTIFICATIONS\n"); + ledger_ble_data.notifications_enabled = 1; + if (!ledger_protocol_data.mtu_negotiated) { + aci_gatt_exchange_config(ledger_ble_data.connection.connection_handle); + } + } + else { + LOG_BLE("NOT REGISTERED FOR NOTIFICATIONS\n"); + ledger_ble_data.notifications_enabled = 0; + } + } + else if ((att_handle == ledger_ble_data.ledger_gatt_write_cmd_characteristic_handle + 1) + && (ledger_ble_data.notifications_enabled) && (ledger_ble_data.connection.encrypted) + && (att_data_length)) { + LOG_BLE("WRITE CMD %d\n", length - 4); + buffer[4] = 0xDE; + buffer[5] = 0xF1; + LEDGER_PROTOCOL_rx(&buffer[4], length - 4); + + if (ledger_protocol_data.rx_apdu_status == APDU_STATUS_COMPLETE) { + check_transfer_mode(G_io_app.transfer_mode); + if (ledger_ble_data.transfer_mode_enable) { + if (U2BE(ledger_ble_data.resp, 0) != SWO_SUCCESS) { + LOG_BLE("Transfer failed 0x%04x\n", U2BE(ledger_ble_data.resp, 0)); + G_io_app.transfer_mode = 0; + check_transfer_mode(G_io_app.transfer_mode); + memcpy(G_io_apdu_buffer, + ledger_protocol_data.rx_apdu_buffer, + ledger_protocol_data.rx_apdu_length); + G_io_app.apdu_length = ledger_protocol_data.rx_apdu_length; + G_io_app.apdu_state = APDU_BLE; + ledger_protocol_data.rx_apdu_length = 0; + ledger_protocol_data.rx_apdu_status = APDU_STATUS_WAITING; + G_io_app.apdu_media = IO_APDU_MEDIA_BLE; + } + else if (ledger_ble_data.resp_length) { + LEDGER_PROTOCOL_tx(ledger_ble_data.resp, ledger_ble_data.resp_length); + ledger_ble_data.resp_length = 0; + notify_chunk(); + } + } + else { + memcpy(G_io_apdu_buffer, + ledger_protocol_data.rx_apdu_buffer, + ledger_protocol_data.rx_apdu_length); + G_io_app.apdu_length = ledger_protocol_data.rx_apdu_length; + G_io_app.apdu_state = APDU_BLE; + ledger_protocol_data.rx_apdu_length = 0; + ledger_protocol_data.rx_apdu_status = APDU_STATUS_WAITING; + G_io_app.apdu_media = IO_APDU_MEDIA_BLE; + } + } + else if (ledger_protocol_data.tx_chunk_length >= 2) { + G_io_app.ble_xfer_timeout = 2000; + notify_chunk(); + G_io_app.apdu_state = APDU_BLE; + } + } + else { + LOG_BLE("ATT MODIFIED %04X %d bytes at offset %d\n", att_handle, att_data_length, offset); + } } static void write_permit_request(uint8_t *buffer, uint16_t length) { - if (length < 3) { - return; - } - - uint16_t att_handle = U2LE(buffer, 0); - uint8_t data_length = buffer[2]; - - ledger_ble_data.wait_write_resp_ack = 1; - - if ( (att_handle == ledger_ble_data.ledger_gatt_write_characteristic_handle+1) - &&(ledger_ble_data.notifications_enabled) - &&(ledger_ble_data.connection.encrypted) - &&(data_length) - ) { - buffer[1] = 0xDE; - buffer[2] = 0xF1; - LEDGER_PROTOCOL_rx(&buffer[1], length-1); - aci_gatt_write_resp(ledger_ble_data.connection.connection_handle, - att_handle, - 0, - HCI_SUCCESS_ERR_CODE, - data_length, - &buffer[3]); - if (ledger_protocol_data.rx_apdu_status == APDU_STATUS_COMPLETE) { - memcpy(G_io_apdu_buffer, - ledger_protocol_data.rx_apdu_buffer, - ledger_protocol_data.rx_apdu_length); - G_io_app.apdu_length = ledger_protocol_data.rx_apdu_length; - ledger_protocol_data.rx_apdu_length = 0; - ledger_protocol_data.rx_apdu_status = APDU_STATUS_WAITING; - G_io_app.apdu_media = IO_APDU_MEDIA_BLE; // for application code - G_io_app.apdu_state = APDU_BLE; // for next call to io_exchange - } - } - else { - LOG_BLE("ATT WRITE %04X %d bytes\n", att_handle, data_length); - ledger_protocol_data.tx_chunk_length = 0; - aci_gatt_write_resp(ledger_ble_data.connection.connection_handle, - att_handle, - 0, - HCI_SUCCESS_ERR_CODE, - data_length, - &buffer[3]); - } + if (length < 3) { + return; + } + + uint16_t att_handle = U2LE(buffer, 0); + uint8_t data_length = buffer[2]; + + ledger_ble_data.wait_write_resp_ack = 1; + + if ((att_handle == ledger_ble_data.ledger_gatt_write_characteristic_handle + 1) + && (ledger_ble_data.notifications_enabled) && (ledger_ble_data.connection.encrypted) + && (data_length)) { + buffer[1] = 0xDE; + buffer[2] = 0xF1; + LEDGER_PROTOCOL_rx(&buffer[1], length - 1); + aci_gatt_write_resp(ledger_ble_data.connection.connection_handle, + att_handle, + 0, + HCI_SUCCESS_ERR_CODE, + data_length, + &buffer[3]); + if (ledger_protocol_data.rx_apdu_status == APDU_STATUS_COMPLETE) { + memcpy(G_io_apdu_buffer, + ledger_protocol_data.rx_apdu_buffer, + ledger_protocol_data.rx_apdu_length); + G_io_app.apdu_length = ledger_protocol_data.rx_apdu_length; + ledger_protocol_data.rx_apdu_length = 0; + ledger_protocol_data.rx_apdu_status = APDU_STATUS_WAITING; + G_io_app.apdu_media = IO_APDU_MEDIA_BLE; // for application code + G_io_app.apdu_state = APDU_BLE; // for next call to io_exchange + } + } + else { + LOG_BLE("ATT WRITE %04X %d bytes\n", att_handle, data_length); + ledger_protocol_data.tx_chunk_length = 0; + aci_gatt_write_resp(ledger_ble_data.connection.connection_handle, + att_handle, + 0, + HCI_SUCCESS_ERR_CODE, + data_length, + &buffer[3]); + } } static void advertising_enable(uint8_t enable) { - if (enable) { - uint8_t buffer[31]; - - get_device_name(); - buffer[0] = AD_TYPE_COMPLETE_LOCAL_NAME; - memcpy(&buffer[1], ledger_ble_data.device_name, ledger_ble_data.device_name_length); - aci_gap_set_discoverable(ADV_IND, - BLE_ADVERTISING_INTERVAL_MIN, - BLE_ADVERTISING_INTERVAL_MAX, - RANDOM_ADDR, - NO_WHITE_LIST_USE, - ledger_ble_data.device_name_length+1, - buffer, - 0, - NULL, - 0, - 0); - } - else { - aci_gap_set_non_discoverable(); - } + if (enable) { + uint8_t buffer[31]; + + get_device_name(); + buffer[0] = AD_TYPE_COMPLETE_LOCAL_NAME; + memcpy(&buffer[1], ledger_ble_data.device_name, ledger_ble_data.device_name_length); + aci_gap_set_discoverable(ADV_IND, + BLE_ADVERTISING_INTERVAL_MIN, + BLE_ADVERTISING_INTERVAL_MAX, + RANDOM_ADDR, + NO_WHITE_LIST_USE, + ledger_ble_data.device_name_length + 1, + buffer, + 0, + NULL, + 0, + 0); + } + else { + aci_gap_set_non_discoverable(); + } } static void start_advertising(void) { - if (G_io_app.name_changed) { - G_io_app.name_changed = 0; - ledger_ble_data.state = BLE_STATE_CONFIGURE_ADVERTISING; - ledger_ble_data.adv_step = BLE_CONFIG_ADV_STEP_IDLE; - } - else { - ledger_ble_data.state = BLE_STATE_CONFIGURE_ADVERTISING; - ledger_ble_data.adv_step = BLE_CONFIG_ADV_STEP_START-1; - } - ledger_ble_data.hci_cmd_opcode = 0xFFFF; - ledger_ble_data.adv_enable = !os_setting_get(OS_SETTING_PLANEMODE, NULL, 0); - configure_advertising_mngr(0); + if (G_io_app.name_changed) { + G_io_app.name_changed = 0; + ledger_ble_data.state = BLE_STATE_CONFIGURE_ADVERTISING; + ledger_ble_data.adv_step = BLE_CONFIG_ADV_STEP_IDLE; + } + else { + ledger_ble_data.state = BLE_STATE_CONFIGURE_ADVERTISING; + ledger_ble_data.adv_step = BLE_CONFIG_ADV_STEP_START - 1; + } + ledger_ble_data.hci_cmd_opcode = 0xFFFF; + ledger_ble_data.adv_enable = !os_setting_get(OS_SETTING_PLANEMODE, NULL, 0); + configure_advertising_mngr(0); } static void notify_chunk(void) { - if (ledger_protocol_data.tx_chunk_length >= 2) { - aci_gatt_update_char_value(ledger_ble_data.ledger_gatt_service_handle, - ledger_ble_data.ledger_gatt_notification_characteristic_handle, - 0, - ledger_protocol_data.tx_chunk_length-2, - &ledger_protocol_data.tx_chunk[2]); - } + if (ledger_protocol_data.tx_chunk_length >= 2) { + aci_gatt_update_char_value(ledger_ble_data.ledger_gatt_service_handle, + ledger_ble_data.ledger_gatt_notification_characteristic_handle, + 0, + ledger_protocol_data.tx_chunk_length - 2, + &ledger_protocol_data.tx_chunk[2]); + } } static void check_transfer_mode(uint8_t enable) { - if (ledger_ble_data.transfer_mode_enable != enable) { - LOG_BLE("LEDGER_BLE_set_transfer_mode %d\n", enable); - } - - if ( (ledger_ble_data.transfer_mode_enable == 0) - &&(enable != 0) - ) { - ledger_ble_data.resp_length = 2; - U2BE_ENCODE(ledger_ble_data.resp, 0, SWO_SUCCESS); - } - - ledger_ble_data.transfer_mode_enable = enable; + if (ledger_ble_data.transfer_mode_enable != enable) { + LOG_BLE("LEDGER_BLE_set_transfer_mode %d\n", enable); + } + + if ((ledger_ble_data.transfer_mode_enable == 0) && (enable != 0)) { + ledger_ble_data.resp_length = 2; + U2BE_ENCODE(ledger_ble_data.resp, 0, SWO_SUCCESS); + } + + ledger_ble_data.transfer_mode_enable = enable; } /* Exported functions --------------------------------------------------------*/ void LEDGER_BLE_init(void) { - G_io_app.enabling_advertising = 0; - G_io_app.disabling_advertising = 0; - - if (ledger_ble_data.clear_pairing == 0xC1) { - memset(&ledger_ble_data, 0, sizeof(ledger_ble_data)); - ledger_ble_data.clear_pairing = 0xC1; - } - else { - memset(&ledger_ble_data, 0, sizeof(ledger_ble_data)); - } - - LEDGER_BLE_get_mac_address(ledger_ble_data.random_address); - ledger_ble_data.hci_cmd_opcode = 0xFFFF; - ledger_ble_data.state = BLE_STATE_INITIALIZING; - ledger_ble_data.init_step = BLE_INIT_STEP_IDLE; - - memset(&ledger_protocol_data, 0, sizeof(ledger_protocol_data)); - ledger_protocol_data.rx_apdu_buffer = ledger_ble_data.apdu_buffer; - ledger_protocol_data.rx_apdu_buffer_max_length = sizeof(ledger_ble_data.apdu_buffer); - LEDGER_PROTOCOL_init(&ledger_protocol_data); - - init_mngr(0, NULL, 0); + G_io_app.enabling_advertising = 0; + G_io_app.disabling_advertising = 0; + + if (ledger_ble_data.clear_pairing == 0xC1) { + memset(&ledger_ble_data, 0, sizeof(ledger_ble_data)); + ledger_ble_data.clear_pairing = 0xC1; + } + else { + memset(&ledger_ble_data, 0, sizeof(ledger_ble_data)); + } + + LEDGER_BLE_get_mac_address(ledger_ble_data.random_address); + ledger_ble_data.hci_cmd_opcode = 0xFFFF; + ledger_ble_data.state = BLE_STATE_INITIALIZING; + ledger_ble_data.init_step = BLE_INIT_STEP_IDLE; + + memset(&ledger_protocol_data, 0, sizeof(ledger_protocol_data)); + ledger_protocol_data.rx_apdu_buffer = ledger_ble_data.apdu_buffer; + ledger_protocol_data.rx_apdu_buffer_max_length = sizeof(ledger_ble_data.apdu_buffer); + LEDGER_PROTOCOL_init(&ledger_protocol_data); + + init_mngr(0, NULL, 0); } -void LEDGER_BLE_send(uint8_t* packet, uint16_t packet_length) +void LEDGER_BLE_send(uint8_t *packet, uint16_t packet_length) { - if ( (ledger_ble_data.transfer_mode_enable != 0) - &&(packet_length == 2) - ) { - G_io_app.apdu_state = APDU_IDLE; - ledger_ble_data.resp_length = 2; - ledger_ble_data.resp[0] = packet[0]; - ledger_ble_data.resp[1] = packet[1]; - if (ledger_protocol_data.rx_apdu_length) { - LEDGER_PROTOCOL_tx(packet, packet_length); - notify_chunk(); - } - } - else { - if ( (ledger_ble_data.resp_length != 0) - &&(U2BE(ledger_ble_data.resp, 0) != SWO_SUCCESS) - ) { - LEDGER_PROTOCOL_tx(ledger_ble_data.resp, ledger_ble_data.resp_length); - } - else { - LEDGER_PROTOCOL_tx(packet, packet_length); - } - ledger_ble_data.resp_length = 0; - - if (ledger_ble_data.wait_write_resp_ack == 0) { - notify_chunk(); - } - } + if ((ledger_ble_data.transfer_mode_enable != 0) && (packet_length == 2)) { + G_io_app.apdu_state = APDU_IDLE; + ledger_ble_data.resp_length = 2; + ledger_ble_data.resp[0] = packet[0]; + ledger_ble_data.resp[1] = packet[1]; + if (ledger_protocol_data.rx_apdu_length) { + LEDGER_PROTOCOL_tx(packet, packet_length); + notify_chunk(); + } + } + else { + if ((ledger_ble_data.resp_length != 0) && (U2BE(ledger_ble_data.resp, 0) != SWO_SUCCESS)) { + LEDGER_PROTOCOL_tx(ledger_ble_data.resp, ledger_ble_data.resp_length); + } + else { + LEDGER_PROTOCOL_tx(packet, packet_length); + } + ledger_ble_data.resp_length = 0; + + if (ledger_ble_data.wait_write_resp_ack == 0) { + notify_chunk(); + } + } } void LEDGER_BLE_receive(void) { - if (G_io_seproxyhal_spi_buffer[3] == HCI_EVENT_PKT_TYPE) { - switch (G_io_seproxyhal_spi_buffer[4]) { - - case HCI_DISCONNECTION_COMPLETE_EVT_CODE: - LOG_BLE("HCI DISCONNECTION COMPLETE code %02X\n", G_io_seproxyhal_spi_buffer[9]); - ledger_ble_data.connection.connection_handle = 0xFFFF; - ledger_ble_data.advertising_enabled = 0; - ledger_ble_data.connection.encrypted = 0; - ledger_ble_data.transfer_mode_enable = 0; - G_io_app.transfer_mode = 0; - end_pairing_ux(BOLOS_UX_ASYNCHMODAL_PAIRING_STATUS_FAILED); - if (G_io_seproxyhal_spi_buffer[9] != 0x28) { // Error code : Instant Passed - start_advertising(); - } - else { - // Workaround to avoid unexpected start advertising event in loop (seems to be a bug in the stack) - LEDGER_BLE_init(); - } - break; - - case HCI_ENCRYPTION_CHANGE_EVT_CODE: - if (U2LE(G_io_seproxyhal_spi_buffer, 7) == ledger_ble_data.connection.connection_handle) { - if (G_io_seproxyhal_spi_buffer[9]) { - LOG_BLE("Link encrypted\n"); - ledger_ble_data.connection.encrypted = 1; - } - else { - LOG_BLE("Link not encrypted\n"); - ledger_ble_data.connection.encrypted = 0; - } - } - else { - LOG_BLE("HCI ENCRYPTION CHANGE EVT %d on connection handle \n", G_io_seproxyhal_spi_buffer[9], - U2LE(G_io_seproxyhal_spi_buffer, 7)); - } - break; - - case HCI_COMMAND_COMPLETE_EVT_CODE: - hci_evt_cmd_complete(&G_io_seproxyhal_spi_buffer[6], - G_io_seproxyhal_spi_buffer[5]); - break; - - case HCI_COMMAND_STATUS_EVT_CODE: - LOG_BLE("HCI COMMAND_STATUS\n"); - break; - - case HCI_ENCRYPTION_KEY_REFRESH_COMPLETE_EVT_CODE: - LOG_BLE("HCI KEY_REFRESH_COMPLETE\n"); - break; - - case HCI_LE_META_EVT_CODE: - hci_evt_le_meta_evt(&G_io_seproxyhal_spi_buffer[6], - G_io_seproxyhal_spi_buffer[5]); - break; - - case HCI_VENDOR_SPECIFIC_DEBUG_EVT_CODE: - hci_evt_vendor(&G_io_seproxyhal_spi_buffer[6], - G_io_seproxyhal_spi_buffer[5]); - break; - - default: - break; - } - } + if (G_io_seproxyhal_spi_buffer[3] == HCI_EVENT_PKT_TYPE) { + switch (G_io_seproxyhal_spi_buffer[4]) { + case HCI_DISCONNECTION_COMPLETE_EVT_CODE: + LOG_BLE("HCI DISCONNECTION COMPLETE code %02X\n", G_io_seproxyhal_spi_buffer[9]); + ledger_ble_data.connection.connection_handle = 0xFFFF; + ledger_ble_data.advertising_enabled = 0; + ledger_ble_data.connection.encrypted = 0; + ledger_ble_data.transfer_mode_enable = 0; + G_io_app.transfer_mode = 0; + end_pairing_ux(BOLOS_UX_ASYNCHMODAL_PAIRING_STATUS_FAILED); + if (G_io_seproxyhal_spi_buffer[9] != 0x28) { // Error code : Instant Passed + start_advertising(); + } + else { + // Workaround to avoid unexpected start advertising event in loop (seems to be a + // bug in the stack) + LEDGER_BLE_init(); + } + break; + + case HCI_ENCRYPTION_CHANGE_EVT_CODE: + if (U2LE(G_io_seproxyhal_spi_buffer, 7) + == ledger_ble_data.connection.connection_handle) { + if (G_io_seproxyhal_spi_buffer[9]) { + LOG_BLE("Link encrypted\n"); + ledger_ble_data.connection.encrypted = 1; + } + else { + LOG_BLE("Link not encrypted\n"); + ledger_ble_data.connection.encrypted = 0; + } + } + else { + LOG_BLE("HCI ENCRYPTION CHANGE EVT %d on connection handle \n", + G_io_seproxyhal_spi_buffer[9], + U2LE(G_io_seproxyhal_spi_buffer, 7)); + } + break; + + case HCI_COMMAND_COMPLETE_EVT_CODE: + hci_evt_cmd_complete(&G_io_seproxyhal_spi_buffer[6], G_io_seproxyhal_spi_buffer[5]); + break; + + case HCI_COMMAND_STATUS_EVT_CODE: + LOG_BLE("HCI COMMAND_STATUS\n"); + break; + + case HCI_ENCRYPTION_KEY_REFRESH_COMPLETE_EVT_CODE: + LOG_BLE("HCI KEY_REFRESH_COMPLETE\n"); + break; + + case HCI_LE_META_EVT_CODE: + hci_evt_le_meta_evt(&G_io_seproxyhal_spi_buffer[6], G_io_seproxyhal_spi_buffer[5]); + break; + + case HCI_VENDOR_SPECIFIC_DEBUG_EVT_CODE: + hci_evt_vendor(&G_io_seproxyhal_spi_buffer[6], G_io_seproxyhal_spi_buffer[5]); + break; + + default: + break; + } + } } void LEDGER_BLE_enable_advertising(uint8_t enable) { - if ( (G_io_app.name_changed) - &&(G_io_app.ble_ready) - &&(!enable) - &&(ledger_ble_data.connection.connection_handle != 0xFFFF) - ) { - G_io_app.name_changed = 0; - } - else if (G_io_app.ble_ready) { - if (enable) { - G_io_app.enabling_advertising = 1; - G_io_app.disabling_advertising = 0; - } - else { - G_io_app.enabling_advertising = 0; - G_io_app.disabling_advertising = 1; - } - advertising_enable(enable); - } + if ((G_io_app.name_changed) && (G_io_app.ble_ready) && (!enable) + && (ledger_ble_data.connection.connection_handle != 0xFFFF)) { + G_io_app.name_changed = 0; + } + else if (G_io_app.ble_ready) { + if (enable) { + G_io_app.enabling_advertising = 1; + G_io_app.disabling_advertising = 0; + } + else { + G_io_app.enabling_advertising = 0; + G_io_app.disabling_advertising = 1; + } + advertising_enable(enable); + } } void LEDGER_BLE_reset_pairings(void) { - if (G_io_app.ble_ready) { - if (ledger_ble_data.connection.connection_handle != 0xFFFF) { - // Connected => force disconnection before clearing - ledger_ble_data.clear_pairing = 0xC1; - LEDGER_BLE_init(); - } - else { - aci_gap_clear_security_db(); - } - } + if (G_io_app.ble_ready) { + if (ledger_ble_data.connection.connection_handle != 0xFFFF) { + // Connected => force disconnection before clearing + ledger_ble_data.clear_pairing = 0xC1; + LEDGER_BLE_init(); + } + else { + aci_gap_clear_security_db(); + } + } } int hci_send_req(struct hci_request *p_cmd, uint8_t async) { - UNUSED(async); + UNUSED(async); - uint16_t opcode = ((p_cmd->ocf) & 0x03ff) | ((p_cmd->ogf) << 10); + uint16_t opcode = ((p_cmd->ocf) & 0x03ff) | ((p_cmd->ogf) << 10); - G_io_seproxyhal_spi_buffer[0] = SEPROXYHAL_TAG_BLE_SEND; - G_io_seproxyhal_spi_buffer[1] = (p_cmd->clen+2)>>8; - G_io_seproxyhal_spi_buffer[2] = (p_cmd->clen+2); - G_io_seproxyhal_spi_buffer[3] = opcode >>8; - G_io_seproxyhal_spi_buffer[4] = opcode; - memmove(G_io_seproxyhal_spi_buffer+5, p_cmd->cparam, p_cmd->clen); - io_seproxyhal_spi_send(G_io_seproxyhal_spi_buffer, 3+p_cmd->clen+2); + G_io_seproxyhal_spi_buffer[0] = SEPROXYHAL_TAG_BLE_SEND; + G_io_seproxyhal_spi_buffer[1] = (p_cmd->clen + 2) >> 8; + G_io_seproxyhal_spi_buffer[2] = (p_cmd->clen + 2); + G_io_seproxyhal_spi_buffer[3] = opcode >> 8; + G_io_seproxyhal_spi_buffer[4] = opcode; + memmove(G_io_seproxyhal_spi_buffer + 5, p_cmd->cparam, p_cmd->clen); + io_seproxyhal_spi_send(G_io_seproxyhal_spi_buffer, 3 + p_cmd->clen + 2); - return 0; + return 0; } -void BLE_power(unsigned char powered, const char *discovered_name) { - UNUSED(discovered_name); +void BLE_power(unsigned char powered, const char *discovered_name) +{ + UNUSED(discovered_name); - LOG_BLE("BLE_power %d\n", powered); - if (powered) { - LEDGER_BLE_init(); - } + LOG_BLE("BLE_power %d\n", powered); + if (powered) { + LEDGER_BLE_init(); + } } diff --git a/lib_blewbxx_impl/stm32_wpan_common.h b/lib_blewbxx_impl/stm32_wpan_common.h index 24b5781a7..9ca394025 100644 --- a/lib_blewbxx_impl/stm32_wpan_common.h +++ b/lib_blewbxx_impl/stm32_wpan_common.h @@ -17,7 +17,6 @@ ****************************************************************************** */ - /* Define to prevent recursive inclusion -------------------------------------*/ #ifndef __STM32_WPAN_COMMON_H #define __STM32_WPAN_COMMON_H @@ -26,18 +25,19 @@ extern "C" { #endif -#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 ( __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 ( __GNUC__ ) - #define __ASM __asm /*!< asm keyword for GNU Compiler */ - #define __INLINE inline /*!< inline keyword for GNU Compiler */ - #define __STATIC_INLINE static inline +#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(__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(__GNUC__) +#define __ASM __asm /*!< asm keyword for GNU Compiler */ +#define __INLINE inline /*!< inline keyword for GNU Compiler */ +#define __STATIC_INLINE static inline #endif #include @@ -47,96 +47,112 @@ extern "C" { #include #include "core_cmFunc.h" - /* -------------------------------- * - * Basic definitions * - * -------------------------------- */ +/* -------------------------------- * + * Basic definitions * + * -------------------------------- */ #undef NULL -#define NULL 0U +#define NULL 0U #undef FALSE -#define FALSE 0U +#define FALSE 0U #undef TRUE -#define TRUE (!0U) +#define TRUE (!0U) - /* -------------------------------- * - * Critical Section definition * - * -------------------------------- */ +/* -------------------------------- * + * Critical Section definition * + * -------------------------------- */ #undef BACKUP_PRIMASK -#define BACKUP_PRIMASK() uint32_t primask_bit= __get_PRIMASK() +#define BACKUP_PRIMASK() uint32_t primask_bit = __get_PRIMASK() #undef DISABLE_IRQ -#define DISABLE_IRQ() __disable_irq() +#define DISABLE_IRQ() __disable_irq() #undef RESTORE_PRIMASK -#define RESTORE_PRIMASK() __set_PRIMASK(primask_bit) +#define RESTORE_PRIMASK() __set_PRIMASK(primask_bit) - /* -------------------------------- * - * Macro delimiters * - * -------------------------------- */ +/* -------------------------------- * + * Macro delimiters * + * -------------------------------- */ #undef M_BEGIN -#define M_BEGIN do { - -#undef M_END -#define M_END } while(0) +#define M_BEGIN do { +#undef M_END +#define M_END \ + } \ + while (0) - /* -------------------------------- * - * Some useful macro definitions * - * -------------------------------- */ +/* -------------------------------- * + * Some useful macro definitions * + * -------------------------------- */ #undef MAX -#define MAX(a, b) (((a) > (b)) ? (a) : (b)) +#define MAX(a, b) (((a) > (b)) ? (a) : (b)) #undef MIN -#define MIN(a, b) (((a) < (b)) ? (a) : (b)) +#define MIN(a, b) (((a) < (b)) ? (a) : (b)) #undef MODINC -#define MODINC( a, m ) M_BEGIN (a)++; if ((a)>=(m)) (a)=0; M_END +#define MODINC(a, m) \ + M_BEGIN(a)++; \ + if ((a) >= (m)) \ + (a) = 0; \ + M_END #undef MODDEC -#define MODDEC( a, m ) M_BEGIN if ((a)==0) (a)=(m); (a)--; M_END +#define MODDEC(a, m) \ + M_BEGIN if ((a) == 0)(a) = (m); \ + (a)--; \ + M_END #undef MODADD -#define MODADD( a, b, m ) M_BEGIN (a)+=(b); if ((a)>=(m)) (a)-=(m); M_END +#define MODADD(a, b, m) \ + M_BEGIN(a) += (b); \ + if ((a) >= (m)) \ + (a) -= (m); \ + M_END #undef MODSUB -#define MODSUB( a, b, m ) MODADD( a, (m)-(b), m ) +#define MODSUB(a, b, m) MODADD(a, (m) - (b), m) #undef ALIGN #ifdef WIN32 #define ALIGN(n) #else -#define ALIGN(n) __attribute__((aligned(n))) +#define ALIGN(n) __attribute__((aligned(n))) #endif #undef PAUSE -#define PAUSE( t ) M_BEGIN \ - volatile int _i; \ - for ( _i = t; _i > 0; _i -- ); \ - M_END +#define PAUSE(t) \ + M_BEGIN \ + volatile int _i; \ + for (_i = t; _i > 0; _i--) \ + ; \ + M_END #undef DIVF -#define DIVF( x, y ) ((x)/(y)) +#define DIVF(x, y) ((x) / (y)) #undef DIVC -#define DIVC( x, y ) (((x)+(y)-1)/(y)) +#define DIVC(x, y) (((x) + (y) -1) / (y)) #undef DIVR -#define DIVR( x, y ) (((x)+((y)/2))/(y)) +#define DIVR(x, y) (((x) + ((y) / 2)) / (y)) #undef SHRR -#define SHRR( x, n ) ((((x)>>((n)-1))+1)>>1) +#define SHRR(x, n) ((((x) >> ((n) -1)) + 1) >> 1) #undef BITN -#define BITN( w, n ) (((w)[(n)/32] >> ((n)%32)) & 1) +#define BITN(w, n) (((w)[(n) / 32] >> ((n) % 32)) & 1) #undef BITNSET -#define BITNSET( w, n, b ) M_BEGIN (w)[(n)/32] |= ((U32)(b))<<((n)%32); M_END +#define BITNSET(w, n, b) \ + M_BEGIN(w)[(n) / 32] |= ((U32) (b)) << ((n) % 32); \ + M_END /* -------------------------------- * * Section attribute * * -------------------------------- */ #undef PLACE_IN_SECTION -#define PLACE_IN_SECTION( __x__ ) __attribute__((section (__x__))) +#define PLACE_IN_SECTION(__x__) __attribute__((section(__x__))) /* ----------------------------------- * * Packed usage (compiler dependent) * @@ -144,21 +160,21 @@ extern "C" { #undef PACKED__ #undef PACKED_STRUCT -#if defined ( __CC_ARM ) - #if defined (__ARMCC_VERSION) && (__ARMCC_VERSION >= 6010050U) - #define PACKED__ __attribute__((packed)) - #define PACKED_STRUCT struct PACKED__ - #else - #define PACKED__(TYPE) __packed TYPE - #define PACKED_STRUCT PACKED__(struct) - #endif -#elif defined ( __GNUC__ ) - #define PACKED__ __attribute__((packed)) - #define PACKED_STRUCT struct PACKED__ -#elif defined (__ICCARM__) - #define PACKED_STRUCT __packed struct +#if defined(__CC_ARM) +#if defined(__ARMCC_VERSION) && (__ARMCC_VERSION >= 6010050U) +#define PACKED__ __attribute__((packed)) +#define PACKED_STRUCT struct PACKED__ +#else +#define PACKED__(TYPE) __packed TYPE +#define PACKED_STRUCT PACKED__(struct) +#endif +#elif defined(__GNUC__) +#define PACKED__ __attribute__((packed)) +#define PACKED_STRUCT struct PACKED__ +#elif defined(__ICCARM__) +#define PACKED_STRUCT __packed struct #elif - #define PACKED_STRUCT __packed struct +#define PACKED_STRUCT __packed struct #endif #ifdef __cplusplus diff --git a/lib_cxng/include/lcx_aead.h b/lib_cxng/include/lcx_aead.h index 6fa937890..dfaead27f 100644 --- a/lib_cxng/include/lcx_aead.h +++ b/lib_cxng/include/lcx_aead.h @@ -1,20 +1,20 @@ /******************************************************************************* -* Ledger Nano S - Secure firmware -* (c) 2022 Ledger -* -* Licensed under the Apache License, Version 2.0 (the "License"); -* you may not use this file except in compliance with the License. -* You may obtain a copy of the License at -* -* http://www.apache.org/licenses/LICENSE-2.0 -* -* Unless required by applicable law or agreed to in writing, software -* distributed under the License is distributed on an "AS IS" BASIS, -* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -* See the License for the specific language governing permissions and -* limitations under the License. -********************************************************************************/ + * Ledger Nano S - Secure firmware + * (c) 2022 Ledger + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + ********************************************************************************/ /** * @file lcx_aead.h @@ -45,17 +45,17 @@ #include "lcx_chacha_poly.h" #endif -#define GCM_MAX_IV_LENGTH 64 -#define MAX_TAG_LENGTH 16 +#define GCM_MAX_IV_LENGTH 64 +#define MAX_TAG_LENGTH 16 /** * @brief Supported AEAD algorithms. */ typedef enum { - CX_AEAD_AES128_GCM, ///< AES-GCM with a 128-bit key - CX_AEAD_AES192_GCM, ///< AES-GCM with a 192-bit key - CX_AEAD_AES256_GCM, ///< AES-GCM with a 256-bit key - CX_AEAD_CHACHA20_POLY1305 ///< CHACHA20-POLY1305 with a 256-bit key + CX_AEAD_AES128_GCM, ///< AES-GCM with a 128-bit key + CX_AEAD_AES192_GCM, ///< AES-GCM with a 192-bit key + CX_AEAD_AES256_GCM, ///< AES-GCM with a 256-bit key + CX_AEAD_CHACHA20_POLY1305 ///< CHACHA20-POLY1305 with a 256-bit key } cx_aead_type_t; /** @@ -63,34 +63,54 @@ typedef enum { * */ typedef struct { - void (*init)(void *ctx); ///< Initializes the context of the base algorithm - cx_err_t (*set_key)(void *ctx, const uint8_t *key, size_t key_len); ///< Sets the key - cx_err_t (*start)(void *ctx, uint32_t mode, const uint8_t *iv, size_t iv_len); ///< Sets the initialization vector - cx_err_t (*update_aad)(void *ctx, const uint8_t *aad, size_t aad_len); ///< Processes the additional authenticated data - cx_err_t (*update)(void *ctx, const uint8_t *input, uint8_t *output, size_t len); ///< Processes the input data - cx_err_t (*finish)(void *ctx, uint8_t *tag, size_t tag_len); ///< Computes the message authenticated code - cx_err_t (*encrypt_and_tag)(void *ctx, - const uint8_t *input, size_t len, - const uint8_t *iv, size_t iv_len, - const uint8_t *aad, size_t aad_len, - uint8_t *output, uint8_t *tag, size_t tag_len); ///< Encrypts the message and computes the MAC + void (*init)(void *ctx); ///< Initializes the context of the base algorithm + cx_err_t (*set_key)(void *ctx, const uint8_t *key, size_t key_len); ///< Sets the key + cx_err_t (*start)(void *ctx, + uint32_t mode, + const uint8_t *iv, + size_t iv_len); ///< Sets the initialization vector + cx_err_t (*update_aad)(void *ctx, + const uint8_t *aad, + size_t aad_len); ///< Processes the additional authenticated data + cx_err_t (*update)(void *ctx, + const uint8_t *input, + uint8_t *output, + size_t len); ///< Processes the input data + cx_err_t (*finish)(void *ctx, + uint8_t *tag, + size_t tag_len); ///< Computes the message authenticated code + cx_err_t (*encrypt_and_tag)(void *ctx, + const uint8_t *input, + size_t len, + const uint8_t *iv, + size_t iv_len, + const uint8_t *aad, + size_t aad_len, + uint8_t *output, + uint8_t *tag, + size_t tag_len); ///< Encrypts the message and computes the MAC - cx_err_t (*auth_decrypt)(void *ctx, - const uint8_t *input, size_t len, - const uint8_t *iv, size_t iv_len, - const uint8_t *aad, size_t aad_len, - uint8_t *output, const uint8_t *tag, size_t tag_len); ///< Decrypts the message and verifies the MAC - cx_err_t (*check_tag)(void *ctx, const uint8_t *tag, size_t tag_len); ///< Checks the MAC + cx_err_t (*auth_decrypt)(void *ctx, + const uint8_t *input, + size_t len, + const uint8_t *iv, + size_t iv_len, + const uint8_t *aad, + size_t aad_len, + uint8_t *output, + const uint8_t *tag, + size_t tag_len); ///< Decrypts the message and verifies the MAC + cx_err_t (*check_tag)(void *ctx, const uint8_t *tag, size_t tag_len); ///< Checks the MAC } cx_aead_base_t; /** * @brief AEAD information. */ typedef struct { - cx_aead_type_t type; ///< AEAD algorithm - size_t key_bitlen; ///< Bit length of the key - size_t block_size; ///< Block size - const cx_aead_base_t *func; ///< Pointer to the generic functions + cx_aead_type_t type; ///< AEAD algorithm + size_t key_bitlen; ///< Bit length of the key + size_t block_size; ///< Block size + const cx_aead_base_t *func; ///< Pointer to the generic functions } cx_aead_info_t; /** @@ -98,9 +118,10 @@ typedef struct { */ typedef struct { - const cx_aead_info_t *info; ///< Pointer to the AEAD information - uint32_t mode; ///< Encrypt or decrypt - void *base_ctx; ///< Pointer to the context of the base algorithm: either AES-GCM or Chacha20-Poly1305 + const cx_aead_info_t *info; ///< Pointer to the AEAD information + uint32_t mode; ///< Encrypt or decrypt + void *base_ctx; ///< Pointer to the context of the base algorithm: either AES-GCM or + ///< Chacha20-Poly1305 } cx_aead_context_t; /** @@ -125,8 +146,8 @@ cx_err_t cx_aead_init(cx_aead_context_t *ctx); /** * @brief AEAD set up. * - * @details The AEAD context must be initialized. This initializes the specific AEAD algorithm context. - * Supported AEAD algorithms: + * @details The AEAD context must be initialized. This initializes the specific AEAD algorithm + * context. Supported AEAD algorithms: * - AES-GCM * - Chacha20-Poly1305 * This must be called after #cx_aead_init and before #cx_aead_set_key. @@ -200,15 +221,19 @@ cx_err_t cx_aead_update_ad(cx_aead_context_t *ctx, const uint8_t *ad, size_t ad_ * * @param[in] in_len Length of the input. * - * @param[out] out Buffer the output data. This must be able to hold at least in_len + block_size. - * This must be not the same buffer as in. + * @param[out] out Buffer the output data. This must be able to hold at least in_len + + * block_size. This must be not the same buffer as in. * * @param[out] out_len The length of the output data. This must not be NULL. * * @return Error code. * */ -cx_err_t cx_aead_update(cx_aead_context_t *ctx, uint8_t *in, size_t in_len, uint8_t *out, size_t *out_len); +cx_err_t cx_aead_update(cx_aead_context_t *ctx, + uint8_t *in, + size_t in_len, + uint8_t *out, + size_t *out_len); /** * @brief Writes the tag of the AEAD cipher. @@ -270,9 +295,17 @@ cx_err_t cx_aead_check_tag(cx_aead_context_t *ctx, const uint8_t *tag, size_t ta * * @return Error code. */ -cx_err_t cx_aead_encrypt(cx_aead_context_t *ctx, const uint8_t *iv, size_t iv_len, - const uint8_t *ad, size_t ad_len, uint8_t *in, size_t in_len, - uint8_t *out, size_t *out_len, uint8_t *tag, size_t tag_len); +cx_err_t cx_aead_encrypt(cx_aead_context_t *ctx, + const uint8_t *iv, + size_t iv_len, + const uint8_t *ad, + size_t ad_len, + uint8_t *in, + size_t in_len, + uint8_t *out, + size_t *out_len, + uint8_t *tag, + size_t tag_len); /** * @brief All-in-one authenticated decryption. @@ -305,9 +338,17 @@ cx_err_t cx_aead_encrypt(cx_aead_context_t *ctx, const uint8_t *iv, size_t iv_le * * @return Error code. */ -cx_err_t cx_aead_decrypt(cx_aead_context_t *ctx, const uint8_t *iv, size_t iv_len, - const uint8_t *ad, size_t ad_len, uint8_t *in, size_t in_len, - uint8_t *out, size_t *out_len, const uint8_t *tag, size_t tag_len); +cx_err_t cx_aead_decrypt(cx_aead_context_t *ctx, + const uint8_t *iv, + size_t iv_len, + const uint8_t *ad, + size_t ad_len, + uint8_t *in, + size_t in_len, + uint8_t *out, + size_t *out_len, + const uint8_t *tag, + size_t tag_len); #endif -#endif // HAVE_AEAD +#endif // HAVE_AEAD diff --git a/lib_cxng/include/lcx_aes.h b/lib_cxng/include/lcx_aes.h index 5d5e7f17f..017dcaa3b 100644 --- a/lib_cxng/include/lcx_aes.h +++ b/lib_cxng/include/lcx_aes.h @@ -1,20 +1,20 @@ /******************************************************************************* -* Ledger Nano S - Secure firmware -* (c) 2022 Ledger -* -* Licensed under the Apache License, Version 2.0 (the "License"); -* you may not use this file except in compliance with the License. -* You may obtain a copy of the License at -* -* http://www.apache.org/licenses/LICENSE-2.0 -* -* Unless required by applicable law or agreed to in writing, software -* distributed under the License is distributed on an "AS IS" BASIS, -* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -* See the License for the specific language governing permissions and -* limitations under the License. -********************************************************************************/ + * Ledger Nano S - Secure firmware + * (c) 2022 Ledger + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + ********************************************************************************/ /** * @file lcx_aes.h @@ -56,15 +56,16 @@ */ cx_err_t cx_aes_init_key_no_throw(const uint8_t *rawkey, size_t key_len, cx_aes_key_t *key); - /** * @deprecated * See #cx_aes_init_key_no_throw */ -DEPRECATED static inline size_t cx_aes_init_key ( const unsigned char * rawkey, unsigned int key_len, cx_aes_key_t * key ) +DEPRECATED static inline size_t cx_aes_init_key(const unsigned char *rawkey, + unsigned int key_len, + cx_aes_key_t *key) { - CX_THROW(cx_aes_init_key_no_throw(rawkey, key_len, key)); - return key_len; + CX_THROW(cx_aes_init_key_no_throw(rawkey, key_len, key)); + return key_len; } /** @@ -113,22 +114,29 @@ DEPRECATED static inline size_t cx_aes_init_key ( const unsigned char * rawkey, */ cx_err_t cx_aes_iv_no_throw(const cx_aes_key_t *key, uint32_t mode, - const uint8_t * iv, + const uint8_t *iv, size_t iv_len, - const uint8_t * in, + const uint8_t *in, size_t in_len, - uint8_t * out, - size_t * out_len); + uint8_t *out, + size_t *out_len); /** * @deprecated * See #cx_aes_iv_no_throw */ -DEPRECATED static inline size_t cx_aes_iv ( const cx_aes_key_t * key, uint32_t mode, unsigned char * iv, unsigned int iv_len, const unsigned char * in, unsigned int in_len, unsigned char * out, unsigned int out_len ) +DEPRECATED static inline size_t cx_aes_iv(const cx_aes_key_t *key, + uint32_t mode, + unsigned char *iv, + unsigned int iv_len, + const unsigned char *in, + unsigned int in_len, + unsigned char *out, + unsigned int out_len) { - size_t out_len_ = out_len; - CX_THROW(cx_aes_iv_no_throw(key, mode, iv, iv_len, in, in_len, out, &out_len_)); - return out_len_; + size_t out_len_ = out_len; + CX_THROW(cx_aes_iv_no_throw(key, mode, iv, iv_len, in, in_len, out, &out_len_)); + return out_len_; } /** @@ -171,17 +179,27 @@ DEPRECATED static inline size_t cx_aes_iv ( const cx_aes_key_t * key, uint32_t m * - CX_INVALID_PARAMETER * - INVALID_PARAMETER */ -cx_err_t cx_aes_no_throw(const cx_aes_key_t *key, uint32_t mode, const uint8_t *in, size_t in_len, uint8_t *out, size_t *out_len); +cx_err_t cx_aes_no_throw(const cx_aes_key_t *key, + uint32_t mode, + const uint8_t *in, + size_t in_len, + uint8_t *out, + size_t *out_len); /** * @deprecated * See #cx_aes_no_throw */ -DEPRECATED static inline size_t cx_aes ( const cx_aes_key_t * key, uint32_t mode, const unsigned char * in, unsigned int in_len, unsigned char * out, unsigned int out_len ) +DEPRECATED static inline size_t cx_aes(const cx_aes_key_t *key, + uint32_t mode, + const unsigned char *in, + unsigned int in_len, + unsigned char *out, + unsigned int out_len) { - size_t out_len_ = out_len; - CX_THROW(cx_aes_no_throw(key, mode, in, in_len, out, &out_len_)); - return out_len_; + size_t out_len_ = out_len; + CX_THROW(cx_aes_no_throw(key, mode, in, in_len, out, &out_len_)); + return out_len_; } /** @@ -218,4 +236,4 @@ cx_err_t cx_aes_dec_block(const cx_aes_key_t *key, const uint8_t *inblock, uint8 #endif -#endif // HAVE_AES +#endif // HAVE_AES diff --git a/lib_cxng/include/lcx_aes_gcm.h b/lib_cxng/include/lcx_aes_gcm.h index 31001657c..d7fd233ab 100644 --- a/lib_cxng/include/lcx_aes_gcm.h +++ b/lib_cxng/include/lcx_aes_gcm.h @@ -1,20 +1,20 @@ /******************************************************************************* -* Ledger Nano S - Secure firmware -* (c) 2022 Ledger -* -* Licensed under the Apache License, Version 2.0 (the "License"); -* you may not use this file except in compliance with the License. -* You may obtain a copy of the License at -* -* http://www.apache.org/licenses/LICENSE-2.0 -* -* Unless required by applicable law or agreed to in writing, software -* distributed under the License is distributed on an "AS IS" BASIS, -* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -* See the License for the specific language governing permissions and -* limitations under the License. -********************************************************************************/ + * Ledger Nano S - Secure firmware + * (c) 2022 Ledger + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + ********************************************************************************/ /** * @file lcx_aes_gcm.h @@ -42,30 +42,46 @@ * @brief AES-GCM context */ typedef struct { - cx_aes_key_t key; ///< AES key - size_t len; ///< Input length - size_t aad_len; ///< Additional data length - uint8_t enc_block[16]; ///< First encrypted block used to compute the tag - uint8_t J0[16]; ///< Counter - uint8_t processed[16]; ///< Processed data - uint8_t hash_key[16]; ///< Ghash key - uint32_t mode; ///< Encrypt or decrypt - uint8_t flag; ///< Indicates either the IV has already been processed or not + cx_aes_key_t key; ///< AES key + size_t len; ///< Input length + size_t aad_len; ///< Additional data length + uint8_t enc_block[16]; ///< First encrypted block used to compute the tag + uint8_t J0[16]; ///< Counter + uint8_t processed[16]; ///< Processed data + uint8_t hash_key[16]; ///< Ghash key + uint32_t mode; ///< Encrypt or decrypt + uint8_t flag; ///< Indicates either the IV has already been processed or not } cx_aes_gcm_context_t; -void cx_aes_gcm_init(cx_aes_gcm_context_t *ctx); +void cx_aes_gcm_init(cx_aes_gcm_context_t *ctx); cx_err_t cx_aes_gcm_set_key(cx_aes_gcm_context_t *ctx, const uint8_t *raw_key, size_t key_len); -cx_err_t cx_aes_gcm_start(cx_aes_gcm_context_t *ctx, uint32_t mode, - const uint8_t *iv, size_t iv_len); +cx_err_t cx_aes_gcm_start(cx_aes_gcm_context_t *ctx, + uint32_t mode, + const uint8_t *iv, + size_t iv_len); cx_err_t cx_aes_gcm_update_aad(cx_aes_gcm_context_t *ctx, const uint8_t *aad, size_t aad_len); cx_err_t cx_aes_gcm_update(cx_aes_gcm_context_t *ctx, const uint8_t *in, uint8_t *out, size_t len); cx_err_t cx_aes_gcm_finish(cx_aes_gcm_context_t *ctx, uint8_t *tag, size_t tag_len); -cx_err_t cx_aes_gcm_encrypt_and_tag(cx_aes_gcm_context_t *ctx, uint8_t *in, size_t len, - const uint8_t *iv, size_t iv_len, const uint8_t *aad, size_t aad_len, - uint8_t *out, uint8_t *tag, size_t tag_len); -cx_err_t cx_aes_gcm_decrypt_and_auth(cx_aes_gcm_context_t *ctx, uint8_t *in, size_t len, - const uint8_t *iv, size_t iv_len, const uint8_t *aad, - size_t aad_len, uint8_t *out, const uint8_t *tag, size_t tag_len); +cx_err_t cx_aes_gcm_encrypt_and_tag(cx_aes_gcm_context_t *ctx, + uint8_t *in, + size_t len, + const uint8_t *iv, + size_t iv_len, + const uint8_t *aad, + size_t aad_len, + uint8_t *out, + uint8_t *tag, + size_t tag_len); +cx_err_t cx_aes_gcm_decrypt_and_auth(cx_aes_gcm_context_t *ctx, + uint8_t *in, + size_t len, + const uint8_t *iv, + size_t iv_len, + const uint8_t *aad, + size_t aad_len, + uint8_t *out, + const uint8_t *tag, + size_t tag_len); cx_err_t cx_aes_gcm_check_tag(cx_aes_gcm_context_t *ctx, const uint8_t *tag, size_t tag_len); #endif -#endif // HAVE_AES && HAVE_AES_GCM +#endif // HAVE_AES && HAVE_AES_GCM diff --git a/lib_cxng/include/lcx_aes_siv.h b/lib_cxng/include/lcx_aes_siv.h index 6f4a7996b..266ebbdfe 100644 --- a/lib_cxng/include/lcx_aes_siv.h +++ b/lib_cxng/include/lcx_aes_siv.h @@ -31,13 +31,14 @@ * */ typedef struct _cx_aes_siv_context { - uint8_t key1[AES_SIV_MAX_KEY_LEN]; ///< Array to store the leftmost bytes of the key - uint8_t key2[AES_SIV_MAX_KEY_LEN]; ///< Array to store the rightmost bytes of the key - size_t key_len; ///< Size of the inner key in bits - uint8_t tag_state[CX_AES_BLOCK_SIZE]; ///< Array to store the S2V state - cx_cipher_id_t cipher_type; ///< Cipher id - uint32_t mode; ///< Encryption or decryption - cx_cipher_context_t *cipher_ctx; ///< Pointer to the cipher context used for both AES-CMAC and AES-CTR + uint8_t key1[AES_SIV_MAX_KEY_LEN]; ///< Array to store the leftmost bytes of the key + uint8_t key2[AES_SIV_MAX_KEY_LEN]; ///< Array to store the rightmost bytes of the key + size_t key_len; ///< Size of the inner key in bits + uint8_t tag_state[CX_AES_BLOCK_SIZE]; ///< Array to store the S2V state + cx_cipher_id_t cipher_type; ///< Cipher id + uint32_t mode; ///< Encryption or decryption + cx_cipher_context_t + *cipher_ctx; ///< Pointer to the cipher context used for both AES-CMAC and AES-CTR } cx_aes_siv_context_t; @@ -70,9 +71,7 @@ cx_err_t cx_aes_siv_init(cx_aes_siv_context_t *ctx); * @param[in] key_bitlen Size of the key in bits. * @return Error code */ -cx_err_t cx_aes_siv_set_key(cx_aes_siv_context_t *ctx, - const uint8_t *key, - size_t key_bitlen); +cx_err_t cx_aes_siv_set_key(cx_aes_siv_context_t *ctx, const uint8_t *key, size_t key_bitlen); /** * @brief Starts the S2V algorithm following RFC5297 specification. @@ -87,9 +86,9 @@ cx_err_t cx_aes_siv_set_key(cx_aes_siv_context_t *ctx, * @return Error code */ cx_err_t cx_aes_siv_start(cx_aes_siv_context_t *ctx, - uint32_t mode, - const uint8_t *iv, - size_t iv_len); + uint32_t mode, + const uint8_t *iv, + size_t iv_len); /** * @brief Processes additional data. @@ -99,9 +98,7 @@ cx_err_t cx_aes_siv_start(cx_aes_siv_context_t *ctx, * @param[in] aad_len Length of the additional data. * @return Error code. */ -cx_err_t cx_aes_siv_update_aad(cx_aes_siv_context_t *ctx, - const uint8_t *aad, - size_t aad_len); +cx_err_t cx_aes_siv_update_aad(cx_aes_siv_context_t *ctx, const uint8_t *aad, size_t aad_len); /** * @brief Processes plaintext or ciphertext with AES-CTR. @@ -114,9 +111,9 @@ cx_err_t cx_aes_siv_update_aad(cx_aes_siv_context_t *ctx, * @return Error code. */ cx_err_t cx_aes_siv_update(cx_aes_siv_context_t *ctx, - const uint8_t *input, - uint8_t *output, - size_t len); + const uint8_t *input, + uint8_t *output, + size_t len); /** * @brief Finishes the S2V algorithm and prepares for the @@ -130,9 +127,9 @@ cx_err_t cx_aes_siv_update(cx_aes_siv_context_t *ctx, * @return Error code. */ cx_err_t cx_aes_siv_finish(cx_aes_siv_context_t *ctx, - const uint8_t *input, - size_t in_len, - uint8_t *tag); + const uint8_t *input, + size_t in_len, + uint8_t *tag); /** * @brief All-in-one encryption. @@ -149,12 +146,12 @@ cx_err_t cx_aes_siv_finish(cx_aes_siv_context_t *ctx, * @return Error code. */ cx_err_t cx_aes_siv_encrypt(cx_aes_siv_context_t *ctx, - const uint8_t *input, - size_t in_len, - const uint8_t *aad, - size_t aad_len, - uint8_t *output, - uint8_t *tag); + const uint8_t *input, + size_t in_len, + const uint8_t *aad, + size_t aad_len, + uint8_t *output, + uint8_t *tag); /** * @brief All-in-one decryption. @@ -171,13 +168,13 @@ cx_err_t cx_aes_siv_encrypt(cx_aes_siv_context_t *ctx, * @return Error code */ cx_err_t cx_aes_siv_decrypt(cx_aes_siv_context_t *ctx, - const uint8_t *input, - size_t in_len, - const uint8_t *aad, - size_t aad_len, - uint8_t *output, - uint8_t *tag); + const uint8_t *input, + size_t in_len, + const uint8_t *aad, + size_t aad_len, + uint8_t *output, + uint8_t *tag); #endif /* LCX_AES_SIV_H */ -#endif // HAVE_AES_SIV +#endif // HAVE_AES_SIV diff --git a/lib_cxng/include/lcx_blake2.h b/lib_cxng/include/lcx_blake2.h index 9781e7191..f93a517d0 100644 --- a/lib_cxng/include/lcx_blake2.h +++ b/lib_cxng/include/lcx_blake2.h @@ -1,20 +1,20 @@ /******************************************************************************* -* Ledger Nano S - Secure firmware -* (c) 2022 Ledger -* -* Licensed under the Apache License, Version 2.0 (the "License"); -* you may not use this file except in compliance with the License. -* You may obtain a copy of the License at -* -* http://www.apache.org/licenses/LICENSE-2.0 -* -* Unless required by applicable law or agreed to in writing, software -* distributed under the License is distributed on an "AS IS" BASIS, -* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -* See the License for the specific language governing permissions and -* limitations under the License. -********************************************************************************/ + * Ledger Nano S - Secure firmware + * (c) 2022 Ledger + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + ********************************************************************************/ /** * @file lcx_blake2.h @@ -35,22 +35,22 @@ /** @private BLAKE2b constants */ enum blake2b_constant { - BLAKE2B_BLOCKBYTES = 128, ///< Size of a block - BLAKE2B_OUTBYTES = 64, ///< Size of the output - BLAKE2B_KEYBYTES = 64, ///< Size of the key - BLAKE2B_SALTBYTES = 16, ///< Size of the salt - BLAKE2B_PERSONALBYTES = 16 ///< Size of the personalization string + BLAKE2B_BLOCKBYTES = 128, ///< Size of a block + BLAKE2B_OUTBYTES = 64, ///< Size of the output + BLAKE2B_KEYBYTES = 64, ///< Size of the key + BLAKE2B_SALTBYTES = 16, ///< Size of the salt + BLAKE2B_PERSONALBYTES = 16 ///< Size of the personalization string }; /** @private BLAKE2b state members */ struct blake2b_state__ { - uint64_t h[8]; ///< Internal state of the hash - uint64_t t[2]; ///< Message byte offset at the end of the current block - uint64_t f[2]; ///< Flag indicating the last block - uint8_t buf[BLAKE2B_BLOCKBYTES]; ///< Buffer for the processed data - size_t buflen; ///< Length of the buffer - size_t outlen; ///< Length of the output - uint8_t last_node; ///< Last node + uint64_t h[8]; ///< Internal state of the hash + uint64_t t[2]; ///< Message byte offset at the end of the current block + uint64_t f[2]; ///< Flag indicating the last block + uint8_t buf[BLAKE2B_BLOCKBYTES]; ///< Buffer for the processed data + size_t buflen; ///< Length of the buffer + size_t outlen; ///< Length of the output + uint8_t last_node; ///< Last node }; /** @private BLAKE2b state */ typedef struct blake2b_state__ blake2b_state; @@ -59,9 +59,9 @@ typedef struct blake2b_state__ blake2b_state; * @brief BLAKE2b context */ struct cx_blake2b_s { - struct cx_hash_header_s header; ///< @copydoc cx_ripemd160_s::header - size_t output_size; ///< Output digest size - struct blake2b_state__ ctx; ///< BLAKE2B state + struct cx_hash_header_s header; ///< @copydoc cx_ripemd160_s::header + size_t output_size; ///< Output digest size + struct blake2b_state__ ctx; ///< BLAKE2B state }; /** Convenience type. See #cx_blake2b_s. */ typedef struct cx_blake2b_s cx_blake2b_t; @@ -84,10 +84,10 @@ cx_err_t cx_blake2b_init_no_throw(cx_blake2b_t *hash, size_t out_len); * @deprecated * See #cx_blake2b_init_no_throw */ -DEPRECATED static inline int cx_blake2b_init ( cx_blake2b_t * hash, unsigned int out_len ) +DEPRECATED static inline int cx_blake2b_init(cx_blake2b_t *hash, unsigned int out_len) { - CX_THROW(cx_blake2b_init_no_throw(hash, out_len)); - return CX_BLAKE2B; + CX_THROW(cx_blake2b_init_no_throw(hash, out_len)); + return CX_BLAKE2B; } /** @@ -112,22 +112,27 @@ DEPRECATED static inline int cx_blake2b_init ( cx_blake2b_t * hash, unsigned int * - CX_INVALID_PARAMETER */ cx_err_t cx_blake2b_init2_no_throw(cx_blake2b_t *hash, - size_t out_len, - uint8_t * salt, - size_t salt_len, - uint8_t * perso, - size_t perso_len); + size_t out_len, + uint8_t *salt, + size_t salt_len, + uint8_t *perso, + size_t perso_len); /** * @deprecated * See #cx_blake2b_init2_no_throw */ -DEPRECATED static inline int cx_blake2b_init2 ( cx_blake2b_t * hash, unsigned int out_len, unsigned char * salt, unsigned int salt_len, unsigned char * perso, unsigned int perso_len ) +DEPRECATED static inline int cx_blake2b_init2(cx_blake2b_t *hash, + unsigned int out_len, + unsigned char *salt, + unsigned int salt_len, + unsigned char *perso, + unsigned int perso_len) { - CX_THROW(cx_blake2b_init2_no_throw(hash, out_len, salt, salt_len, perso, perso_len)); - return CX_BLAKE2B; + CX_THROW(cx_blake2b_init2_no_throw(hash, out_len, salt, salt_len, perso, perso_len)); + return CX_BLAKE2B; } #endif -#endif // HAVE_BLAKE2 +#endif // HAVE_BLAKE2 diff --git a/lib_cxng/include/lcx_blake3.h b/lib_cxng/include/lcx_blake3.h index 93b261168..fa4571c63 100644 --- a/lib_cxng/include/lcx_blake3.h +++ b/lib_cxng/include/lcx_blake3.h @@ -1,20 +1,20 @@ /******************************************************************************* -* Ledger Nano S - Secure firmware -* (c) 2022 Ledger -* -* Licensed under the Apache License, Version 2.0 (the "License"); -* you may not use this file except in compliance with the License. -* You may obtain a copy of the License at -* -* http://www.apache.org/licenses/LICENSE-2.0 -* -* Unless required by applicable law or agreed to in writing, software -* distributed under the License is distributed on an "AS IS" BASIS, -* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -* See the License for the specific language governing permissions and -* limitations under the License. -********************************************************************************/ + * Ledger Nano S - Secure firmware + * (c) 2022 Ledger + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + ********************************************************************************/ /** * @file lcx_blake3.h * @brief BLAKE3 hash function. @@ -44,43 +44,43 @@ // i.e. it is the maximal number of chunks that can be stored within the cv stack. // The default input length is at most (2**64 - 1) but due to memory constraints // it is set to (2**20 - 1) -#define BLAKE3_MAX_INPUT_LEN_POWER 20 -#define BLAKE3_MAX_INPUT_LEN (1 << BLAKE3_MAX_INPUT_LEN_POWER) +#define BLAKE3_MAX_INPUT_LEN_POWER 20 +#define BLAKE3_MAX_INPUT_LEN (1 << BLAKE3_MAX_INPUT_LEN_POWER) -#define BLAKE3_BLOCK_LEN 64 -#define BLAKE3_OUT_LEN 32 -#define BLAKE3_MAX_DEPTH (BLAKE3_MAX_INPUT_LEN_POWER - 10) -#define BLAKE3_MAX_STACK_SIZE (BLAKE3_MAX_DEPTH + 1) * BLAKE3_OUT_LEN -#define BLAKE3_WORD_SIZE 32 -#define BLAKE3_NB_OF_WORDS 8 +#define BLAKE3_BLOCK_LEN 64 +#define BLAKE3_OUT_LEN 32 +#define BLAKE3_MAX_DEPTH (BLAKE3_MAX_INPUT_LEN_POWER - 10) +#define BLAKE3_MAX_STACK_SIZE (BLAKE3_MAX_DEPTH + 1) * BLAKE3_OUT_LEN +#define BLAKE3_WORD_SIZE 32 +#define BLAKE3_NB_OF_WORDS 8 /** * @brief Blake3 chunk state */ typedef struct { - uint32_t cv[BLAKE3_NB_OF_WORDS]; ///< Chaining value - uint64_t t; ///< Chunk counter - uint8_t buffer[BLAKE3_BLOCK_LEN]; ///< Buffer for the next block - uint8_t buffer_len; ///< Number of bytes of the buffer - uint8_t blocks_compressed; ///< Number of compressed blocks - uint8_t d; ///< Flags + uint32_t cv[BLAKE3_NB_OF_WORDS]; ///< Chaining value + uint64_t t; ///< Chunk counter + uint8_t buffer[BLAKE3_BLOCK_LEN]; ///< Buffer for the next block + uint8_t buffer_len; ///< Number of bytes of the buffer + uint8_t blocks_compressed; ///< Number of compressed blocks + uint8_t d; ///< Flags } cx_blake3_state_t; /** * @brief Blake3 context */ typedef struct { - uint32_t key[BLAKE3_NB_OF_WORDS]; ///< Key words - // the stack contains at most (BLAKE3_MAX_DEPTH + 1) - // 32-byte chaining values - uint8_t cv_stack[BLAKE3_MAX_STACK_SIZE]; ///< Stack of chaining values - uint8_t cv_stack_len; ///< Current size of the CV stack - // contains the 32-byte chaining value (CV) - // of the previous block, - // the 64-byte input buffer for the next block - // the counter t and the flags d - cx_blake3_state_t chunk; ///< Chunk state - bool is_init; ///< Context initialization + uint32_t key[BLAKE3_NB_OF_WORDS]; ///< Key words + // the stack contains at most (BLAKE3_MAX_DEPTH + 1) + // 32-byte chaining values + uint8_t cv_stack[BLAKE3_MAX_STACK_SIZE]; ///< Stack of chaining values + uint8_t cv_stack_len; ///< Current size of the CV stack + // contains the 32-byte chaining value (CV) + // of the previous block, + // the 64-byte input buffer for the next block + // the counter t and the flags d + cx_blake3_state_t chunk; ///< Chunk state + bool is_init; ///< Context initialization } cx_blake3_t; /** @@ -101,8 +101,11 @@ typedef struct { * * @return Error code. */ -cx_err_t cx_blake3_init(cx_blake3_t *hash, uint8_t mode, const unsigned char *key, - const void *context, unsigned int context_len); +cx_err_t cx_blake3_init(cx_blake3_t *hash, + uint8_t mode, + const unsigned char *key, + const void *context, + unsigned int context_len); /** * @brief Computes the digest of a message using blake3. @@ -121,8 +124,12 @@ cx_err_t cx_blake3_init(cx_blake3_t *hash, uint8_t mode, const unsigned char *ke * * @return Error code */ -cx_err_t cx_blake3(cx_blake3_t *hash, uint8_t mode, const void *input, - size_t input_len, uint8_t *out, size_t out_len); +cx_err_t cx_blake3(cx_blake3_t *hash, + uint8_t mode, + const void *input, + size_t input_len, + uint8_t *out, + size_t out_len); /** * @brief Adds more data to process to the context. @@ -150,5 +157,5 @@ cx_err_t cx_blake3_update(cx_blake3_t *hash, const void *input, size_t input_len */ cx_err_t cx_blake3_final(cx_blake3_t *hash, uint8_t *output, size_t out_len); -#endif // LCX_BLAKE3_H -#endif // HAVE_BLAKE3 +#endif // LCX_BLAKE3_H +#endif // HAVE_BLAKE3 diff --git a/lib_cxng/include/lcx_chacha.h b/lib_cxng/include/lcx_chacha.h index 6e3b7093c..171fa6a09 100644 --- a/lib_cxng/include/lcx_chacha.h +++ b/lib_cxng/include/lcx_chacha.h @@ -1,20 +1,20 @@ /******************************************************************************* -* Ledger Nano S - Secure firmware -* (c) 2022 Ledger -* -* Licensed under the Apache License, Version 2.0 (the "License"); -* you may not use this file except in compliance with the License. -* You may obtain a copy of the License at -* -* http://www.apache.org/licenses/LICENSE-2.0 -* -* Unless required by applicable law or agreed to in writing, software -* distributed under the License is distributed on an "AS IS" BASIS, -* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -* See the License for the specific language governing permissions and -* limitations under the License. -********************************************************************************/ + * Ledger Nano S - Secure firmware + * (c) 2022 Ledger + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT 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(HAVE_CHACHA) /** @@ -41,10 +41,10 @@ * @brief Chacha context */ typedef struct { - uint32_t nrounds; ///< Number of rounds: 8, 12 or 20 - uint32_t state[16]; ///< Initial state array - uint32_t block[16]; ///< State array after block processing - uint32_t pos; ///< Block count + uint32_t nrounds; ///< Number of rounds: 8, 12 or 20 + uint32_t state[16]; ///< Initial state array + uint32_t block[16]; ///< State array after block processing + uint32_t pos; ///< Block count } cx_chacha_context_t; /** @@ -122,7 +122,10 @@ cx_err_t cx_chacha_start(cx_chacha_context_t *ctx, const uint8_t *iv, size_t iv_ * * @return Error code */ -cx_err_t cx_chacha_update(cx_chacha_context_t *ctx, const uint8_t *input, uint8_t *output, size_t len); +cx_err_t cx_chacha_update(cx_chacha_context_t *ctx, + const uint8_t *input, + uint8_t *output, + size_t len); /** * @brief Encrypt or decrypt data with Chacha and a given key and nonce. @@ -147,11 +150,14 @@ cx_err_t cx_chacha_update(cx_chacha_context_t *ctx, const uint8_t *input, uint8_ * * @return Error code. */ -cx_err_t cx_chacha_cipher(uint32_t nrounds, - const uint8_t *key, size_t key_len, - const uint8_t *iv, size_t iv_len, +cx_err_t cx_chacha_cipher(uint32_t nrounds, + const uint8_t *key, + size_t key_len, + const uint8_t *iv, + size_t iv_len, const uint8_t *input, - uint8_t *output, size_t len); + uint8_t *output, + size_t len); -#endif /* LCX_CHACHA_H */ -#endif // HAVE_CHACHA +#endif /* LCX_CHACHA_H */ +#endif // HAVE_CHACHA diff --git a/lib_cxng/include/lcx_chacha_poly.h b/lib_cxng/include/lcx_chacha_poly.h index 4a782cec4..74f2eec87 100644 --- a/lib_cxng/include/lcx_chacha_poly.h +++ b/lib_cxng/include/lcx_chacha_poly.h @@ -1,20 +1,20 @@ /******************************************************************************* -* Ledger Nano S - Secure firmware -* (c) 2022 Ledger -* -* Licensed under the Apache License, Version 2.0 (the "License"); -* you may not use this file except in compliance with the License. -* You may obtain a copy of the License at -* -* http://www.apache.org/licenses/LICENSE-2.0 -* -* Unless required by applicable law or agreed to in writing, software -* distributed under the License is distributed on an "AS IS" BASIS, -* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -* See the License for the specific language governing permissions and -* limitations under the License. -********************************************************************************/ + * Ledger Nano S - Secure firmware + * (c) 2022 Ledger + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT 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(HAVE_CHACHA_POLY) #if defined(HAVE_POLY1305) && defined(HAVE_CHACHA) @@ -28,7 +28,6 @@ * @version 1.0 **/ - #ifndef LCX_CHACHA_POLY_H #define LCX_CHACHA_POLY_H @@ -38,47 +37,56 @@ #include typedef struct { - cx_chacha_context_t chacha20_ctx; ///< The ChaCha20 context. - cx_poly1305_context_t poly1305_ctx; ///< The Poly1305 context. - size_t aad_len; ///< The length in bytes of the Additional Authenticated Data. - size_t ciphertext_len; ///< The length in bytes of the ciphertext. - uint32_t state; ///< The current state of the context. - uint32_t mode; ///< Cipher mode (encrypt or decrypt). + cx_chacha_context_t chacha20_ctx; ///< The ChaCha20 context. + cx_poly1305_context_t poly1305_ctx; ///< The Poly1305 context. + size_t aad_len; ///< The length in bytes of the Additional Authenticated Data. + size_t ciphertext_len; ///< The length in bytes of the ciphertext. + uint32_t state; ///< The current state of the context. + uint32_t mode; ///< Cipher mode (encrypt or decrypt). } cx_chachapoly_context_t; void cx_chachapoly_init(cx_chachapoly_context_t *ctx); -cx_err_t cx_chachapoly_set_key(cx_chachapoly_context_t *ctx, - const uint8_t *key, size_t key_len); +cx_err_t cx_chachapoly_set_key(cx_chachapoly_context_t *ctx, const uint8_t *key, size_t key_len); -cx_err_t cx_chachapoly_start(cx_chachapoly_context_t *ctx, uint32_t mode, - const uint8_t *iv, size_t iv_len); +cx_err_t cx_chachapoly_start(cx_chachapoly_context_t *ctx, + uint32_t mode, + const uint8_t *iv, + size_t iv_len); -cx_err_t cx_chachapoly_update_aad(cx_chachapoly_context_t *ctx, - const uint8_t *aad, - size_t aad_len); +cx_err_t cx_chachapoly_update_aad(cx_chachapoly_context_t *ctx, const uint8_t *aad, size_t aad_len); cx_err_t cx_chachapoly_update(cx_chachapoly_context_t *ctx, - const uint8_t *input, - uint8_t *output, size_t len); + const uint8_t *input, + uint8_t *output, + size_t len); -cx_err_t cx_chachapoly_finish(cx_chachapoly_context_t *ctx, - uint8_t *tag, size_t tag_len); +cx_err_t cx_chachapoly_finish(cx_chachapoly_context_t *ctx, uint8_t *tag, size_t tag_len); cx_err_t cx_chachapoly_encrypt_and_tag(cx_chachapoly_context_t *ctx, - const uint8_t *input, size_t len, - const uint8_t *iv, size_t iv_len, - const uint8_t *aad, size_t aad_len, - uint8_t *output, uint8_t *tag, size_t tag_len); + const uint8_t *input, + size_t len, + const uint8_t *iv, + size_t iv_len, + const uint8_t *aad, + size_t aad_len, + uint8_t *output, + uint8_t *tag, + size_t tag_len); cx_err_t cx_chachapoly_decrypt_and_auth(cx_chachapoly_context_t *ctx, - const uint8_t *input, size_t len, - const uint8_t *iv, size_t iv_len, - const uint8_t *aad, size_t aad_len, - uint8_t *output, const uint8_t *tag, size_t tag_len); + const uint8_t *input, + size_t len, + const uint8_t *iv, + size_t iv_len, + const uint8_t *aad, + size_t aad_len, + uint8_t *output, + const uint8_t *tag, + size_t tag_len); cx_err_t cx_chachapoly_check_tag(cx_chachapoly_context_t *ctx, const uint8_t *tag, size_t tag_len); -#endif /* LCX_CHACHA_POLY_H */ -#endif // HAVE_POLY1305 && HAVE_CHACHA -#endif // HAVE_CHACHA_POLY +#endif /* LCX_CHACHA_POLY_H */ +#endif // HAVE_POLY1305 && HAVE_CHACHA +#endif // HAVE_CHACHA_POLY diff --git a/lib_cxng/include/lcx_cipher.h b/lib_cxng/include/lcx_cipher.h index 4ce7e375a..db585cc67 100644 --- a/lib_cxng/include/lcx_cipher.h +++ b/lib_cxng/include/lcx_cipher.h @@ -26,68 +26,74 @@ /** CMAC context */ typedef struct { - uint8_t state[CMAC_MAX_BLOCK_LENGTH]; - uint8_t unprocessed_block[CMAC_MAX_BLOCK_LENGTH]; - size_t unprocessed_len; + uint8_t state[CMAC_MAX_BLOCK_LENGTH]; + uint8_t unprocessed_block[CMAC_MAX_BLOCK_LENGTH]; + size_t unprocessed_len; } cx_cmac_context_t; -#endif // HAVE_CMAC +#endif // HAVE_CMAC /** Supported cipher identifiers */ typedef enum { - CX_CIPHER_NONE = 0, ///< No cipher - CX_CIPHER_AES_128, ///< AES with a 128-bit key - CX_CIPHER_AES_192, ///< AES with a 192-bit key - CX_CIPHER_AES_256, ///< AES with a 256-bit key -} cx_cipher_id_t ; + CX_CIPHER_NONE = 0, ///< No cipher + CX_CIPHER_AES_128, ///< AES with a 128-bit key + CX_CIPHER_AES_192, ///< AES with a 192-bit key + CX_CIPHER_AES_256, ///< AES with a 256-bit key +} cx_cipher_id_t; /** Generic key structure */ typedef struct { - unsigned int size; - unsigned char keys[32]; + unsigned int size; + unsigned char keys[32]; } cipher_key_t; - - /** Base cipher information */ typedef struct { - cx_err_t (*enc_func)(const uint8_t *in_block, uint8_t *out_block); ///< Encryption function - cx_err_t (*dec_func)(const uint8_t *in_block, uint8_t *out_block); ///< Decryption function - cx_err_t (*ctr_func)(const cipher_key_t *ctx_key, size_t len, size_t *nc_off, uint8_t *nonce_counter, - uint8_t *stream_block, const uint8_t *input, uint8_t *output); ///< Encryption in CTR mode - cx_err_t (*setkey_func)(const cipher_key_t *ctx_key, uint32_t operation, const uint8_t *key, - uint32_t key_bitlen); ///< Set key for encryption or decryption - cx_err_t (*ctx_reset)(void); ///< Reset + cx_err_t (*enc_func)(const uint8_t *in_block, uint8_t *out_block); ///< Encryption function + cx_err_t (*dec_func)(const uint8_t *in_block, uint8_t *out_block); ///< Decryption function + cx_err_t (*ctr_func)(const cipher_key_t *ctx_key, + size_t len, + size_t *nc_off, + uint8_t *nonce_counter, + uint8_t *stream_block, + const uint8_t *input, + uint8_t *output); ///< Encryption in CTR mode + cx_err_t (*setkey_func)(const cipher_key_t *ctx_key, + uint32_t operation, + const uint8_t *key, + uint32_t key_bitlen); ///< Set key for encryption or decryption + cx_err_t (*ctx_reset)(void); ///< Reset } cx_cipher_base_t; /** Cipher information */ typedef struct { - uint32_t key_bitlen; ///< Key size - uint32_t iv_size; ///< Initialization vector size - uint32_t block_size; ///< Block size - const cx_cipher_base_t *base; /// Structure for base cipher + uint32_t key_bitlen; ///< Key size + uint32_t iv_size; ///< Initialization vector size + uint32_t block_size; ///< Block size + const cx_cipher_base_t *base; /// Structure for base cipher } cx_cipher_info_t; /** Generic cipher context */ typedef struct { - const cx_cipher_info_t *cipher_info; ///< Cipher information - uint32_t key_bitlen; ///< Key size in bits - uint32_t operation; ///< Operation: encryption or decryption - void (*add_padding)(uint8_t *output, size_t out_len, size_t data_len); ///< Padding function - cx_err_t (*get_padding)(uint8_t *input, size_t in_len, size_t *data_len); ///< Check the padding - uint8_t unprocessed_data[MAX_BLOCK_LENGTH]; ///< Data to process - size_t unprocessed_len; ///< Length of data to process - uint8_t iv[MAX_IV_LENGTH]; ///< Initiaization vector - size_t iv_size; ///< Length of the initialization vector - uint32_t mode; ///< Mode of operation: ECB, CBC, CTR - uint8_t sig[MAX_BLOCK_LENGTH]; ///< Last block to be verified - const cipher_key_t *cipher_key; ///< Cipher-specific context + const cx_cipher_info_t *cipher_info; ///< Cipher information + uint32_t key_bitlen; ///< Key size in bits + uint32_t operation; ///< Operation: encryption or decryption + void (*add_padding)(uint8_t *output, size_t out_len, size_t data_len); ///< Padding function + cx_err_t (*get_padding)(uint8_t *input, + size_t in_len, + size_t *data_len); ///< Check the padding + uint8_t unprocessed_data[MAX_BLOCK_LENGTH]; ///< Data to process + size_t unprocessed_len; ///< Length of data to process + uint8_t iv[MAX_IV_LENGTH]; ///< Initiaization vector + size_t iv_size; ///< Length of the initialization vector + uint32_t mode; ///< Mode of operation: ECB, CBC, CTR + uint8_t sig[MAX_BLOCK_LENGTH]; ///< Last block to be verified + const cipher_key_t *cipher_key; ///< Cipher-specific context #ifdef HAVE_CMAC - cx_cmac_context_t *cmac_ctx; -#endif // HAVE_CMAC + cx_cmac_context_t *cmac_ctx; +#endif // HAVE_CMAC } cx_cipher_context_t; - /** * @brief Initialize a cipher context as NONE. * @@ -143,7 +149,10 @@ cx_err_t cx_cipher_setup(cx_cipher_context_t *ctx, const cx_cipher_id_t type, ui * - CX_INVALID_PARAMETER_SIZE * - CX_INVALID_PARAMETER_VALUE */ -cx_err_t cx_cipher_setkey(cx_cipher_context_t *ctx, const uint8_t *key, uint32_t key_bitlen, uint32_t operation); +cx_err_t cx_cipher_setkey(cx_cipher_context_t *ctx, + const uint8_t *key, + uint32_t key_bitlen, + uint32_t operation); /** * @brief Set the initialization vector. @@ -211,7 +220,11 @@ cx_err_t cx_cipher_set_padding(cx_cipher_context_t *ctx, uint32_t padding); * - CX_INVALID_PARAMETER * - CX_INVALID_PARAMETER_VALUE */ -cx_err_t cx_cipher_update(cx_cipher_context_t *ctx, const uint8_t *input, size_t in_len, uint8_t *output, size_t *out_len); +cx_err_t cx_cipher_update(cx_cipher_context_t *ctx, + const uint8_t *input, + size_t in_len, + uint8_t *output, + size_t *out_len); /** * @brief Finalize the operation. @@ -265,8 +278,13 @@ cx_err_t cx_cipher_finish(cx_cipher_context_t *ctx, uint8_t *output, size_t *out * - CX_INVALID_PARAMETER * - CX_INVALID_PARAMETER_VALUE */ -cx_err_t cx_cipher_enc_dec(cx_cipher_context_t *ctx, const uint8_t *iv, size_t iv_len, const uint8_t *input, size_t in_len, - uint8_t *output, size_t *out_len); +cx_err_t cx_cipher_enc_dec(cx_cipher_context_t *ctx, + const uint8_t *iv, + size_t iv_len, + const uint8_t *input, + size_t in_len, + uint8_t *output, + size_t *out_len); void cx_cipher_reset(cx_cipher_context_t *ctx); diff --git a/lib_cxng/include/lcx_cmac.h b/lib_cxng/include/lcx_cmac.h index 1357ef8ee..87ee442a5 100644 --- a/lib_cxng/include/lcx_cmac.h +++ b/lib_cxng/include/lcx_cmac.h @@ -13,24 +13,19 @@ #include "lcx_cipher.h" #include "cx_errors.h" -cx_err_t cx_cmac_start(cx_cipher_context_t *ctx, - const uint8_t *key, - size_t key_bitlen); +cx_err_t cx_cmac_start(cx_cipher_context_t *ctx, const uint8_t *key, size_t key_bitlen); -cx_err_t cx_cmac_update(cx_cipher_context_t *ctx, - const uint8_t *input, - size_t in_len); +cx_err_t cx_cmac_update(cx_cipher_context_t *ctx, const uint8_t *input, size_t in_len); -cx_err_t cx_cmac_finish(cx_cipher_context_t *ctx, - uint8_t *output); +cx_err_t cx_cmac_finish(cx_cipher_context_t *ctx, uint8_t *output); cx_err_t cx_cmac(const cx_cipher_id_t type, - const uint8_t *key, - size_t key_bitlen, - const uint8_t *input, - size_t in_len, - uint8_t *output); + const uint8_t *key, + size_t key_bitlen, + const uint8_t *input, + size_t in_len, + uint8_t *output); #endif /* LCX_CMAC_H */ -#endif // HAVE_CMAC +#endif // HAVE_CMAC diff --git a/lib_cxng/include/lcx_common.h b/lib_cxng/include/lcx_common.h index 4563942ff..5afd4cf25 100644 --- a/lib_cxng/include/lcx_common.h +++ b/lib_cxng/include/lcx_common.h @@ -1,20 +1,20 @@ /******************************************************************************* -* Ledger Nano S - Secure firmware -* (c) 2022 Ledger -* -* Licensed under the Apache License, Version 2.0 (the "License"); -* you may not use this file except in compliance with the License. -* You may obtain a copy of the License at -* -* http://www.apache.org/licenses/LICENSE-2.0 -* -* Unless required by applicable law or agreed to in writing, software -* distributed under the License is distributed on an "AS IS" BASIS, -* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -* See the License for the specific language governing permissions and -* limitations under the License. -********************************************************************************/ + * Ledger Nano S - Secure firmware + * (c) 2022 Ledger + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + ********************************************************************************/ /** * @file lcx_common.h @@ -38,7 +38,7 @@ #define NATIVE_64BITS #endif -#ifndef NATIVE_64BITS // NO 64BITS +#ifndef NATIVE_64BITS // NO 64BITS /** * @brief 64-bit types, native or by-hands, depending on target and/or compiler * support. @@ -47,11 +47,11 @@ */ struct uint64_s { #ifdef ARCH_LITTLE_ENDIAN - uint32_t l; ///< 32 least significant bits - uint32_t h; ///< 32 most significant bits + uint32_t l; ///< 32 least significant bits + uint32_t h; ///< 32 most significant bits #else - uint32_t h; - uint32_t l; + uint32_t h; + uint32_t l; #endif }; typedef struct uint64_s uint64bits_t; @@ -59,6 +59,7 @@ typedef struct uint64_s uint64bits_t; typedef uint64_t uint64bits_t; #endif +// clang-format off /** * @brief Cryptography flags * @details Some functions take **logical or** of various flags. @@ -96,6 +97,7 @@ typedef uint64_t uint64bits_t; * | 2:1 | 0000000000000000 | CX_DECRYPT | Decryption | AES | * | 0 | 0000000000000001 | CX_LAST | Last block | | */ +// clang-format on #define CX_FLAG /** @@ -112,59 +114,59 @@ typedef uint64_t uint64bits_t; * Bit 2:1: Signature and/or encryption */ #define CX_MASK_SIGCRYPT (3 << 1) -#define CX_ENCRYPT (2 << 1) -#define CX_DECRYPT (0 << 1) -#define CX_SIGN (CX_SIG_MODE | CX_ENCRYPT) -#define CX_VERIFY (CX_SIG_MODE | CX_DECRYPT) +#define CX_ENCRYPT (2 << 1) +#define CX_DECRYPT (0 << 1) +#define CX_SIGN (CX_SIG_MODE | CX_ENCRYPT) +#define CX_VERIFY (CX_SIG_MODE | CX_DECRYPT) /** * Bit 5:3: Padding */ -#define CX_MASK_PAD (7 << 3) -#define CX_PAD_NONE (0 << 3) -#define CX_PAD_ISO9797M1 (1 << 3) -#define CX_PAD_ISO9797M2 (2 << 3) -#define CX_PAD_PKCS1_1o5 (3 << 3) -#define CX_PAD_PKCS1_PSS (4 << 3) +#define CX_MASK_PAD (7 << 3) +#define CX_PAD_NONE (0 << 3) +#define CX_PAD_ISO9797M1 (1 << 3) +#define CX_PAD_ISO9797M2 (2 << 3) +#define CX_PAD_PKCS1_1o5 (3 << 3) +#define CX_PAD_PKCS1_PSS (4 << 3) #define CX_PAD_PKCS1_OAEP (5 << 3) /** * Bit 8:6 AES chaining */ #define CX_MASK_CHAIN (7 << 6) -#define CX_CHAIN_ECB (0 << 6) -#define CX_CHAIN_CBC (1 << 6) -#define CX_CHAIN_CTR (2 << 6) -#define CX_CHAIN_CFB (3 << 6) -#define CX_CHAIN_OFB (4 << 6) +#define CX_CHAIN_ECB (0 << 6) +#define CX_CHAIN_CBC (1 << 6) +#define CX_CHAIN_CTR (2 << 6) +#define CX_CHAIN_CFB (3 << 6) +#define CX_CHAIN_OFB (4 << 6) /** * Bit 8:6 ECC variant */ #define CX_MASK_ECC_VARIANT (7 << 6) -#define CX_NO_CANONICAL (1 << 6) +#define CX_NO_CANONICAL (1 << 6) /** * Bit 11:9 Random number generation */ -#define CX_MASK_RND (7 << 9) -#define CX_RND_PRNG (1 << 9) -#define CX_RND_TRNG (2 << 9) -#define CX_RND_RFC6979 (3 << 9) +#define CX_MASK_RND (7 << 9) +#define CX_RND_PRNG (1 << 9) +#define CX_RND_TRNG (2 << 9) +#define CX_RND_RFC6979 (3 << 9) #define CX_RND_PROVIDED (4 << 9) /** * Bit 14:12: ECDH and ECSCHNORR specificities */ -#define CX_MASK_EC (7 << 12) -#define CX_ECSCHNORR_BIP0340 (0 << 12) -#define CX_ECDH_POINT (1 << 12) -#define CX_ECDH_X (2 << 12) +#define CX_MASK_EC (7 << 12) +#define CX_ECSCHNORR_BIP0340 (0 << 12) +#define CX_ECDH_POINT (1 << 12) +#define CX_ECDH_X (2 << 12) #define CX_ECSCHNORR_ISO14888_XY (3 << 12) -#define CX_ECSCHNORR_ISO14888_X (4 << 12) -#define CX_ECSCHNORR_BSI03111 (5 << 12) -#define CX_ECSCHNORR_LIBSECP (6 << 12) -#define CX_ECSCHNORR_Z (7 << 12) +#define CX_ECSCHNORR_ISO14888_X (4 << 12) +#define CX_ECSCHNORR_BSI03111 (5 << 12) +#define CX_ECSCHNORR_LIBSECP (6 << 12) +#define CX_ECSCHNORR_Z (7 << 12) /** * Bit 15: No reinitialization diff --git a/lib_cxng/include/lcx_crc.h b/lib_cxng/include/lcx_crc.h index 443b28e49..884d5fb99 100644 --- a/lib_cxng/include/lcx_crc.h +++ b/lib_cxng/include/lcx_crc.h @@ -1,20 +1,20 @@ /******************************************************************************* -* Ledger Nano S - Secure firmware -* (c) 2022 Ledger -* -* Licensed under the Apache License, Version 2.0 (the "License"); -* you may not use this file except in compliance with the License. -* You may obtain a copy of the License at -* -* http://www.apache.org/licenses/LICENSE-2.0 -* -* Unless required by applicable law or agreed to in writing, software -* distributed under the License is distributed on an "AS IS" BASIS, -* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -* See the License for the specific language governing permissions and -* limitations under the License. -********************************************************************************/ + * Ledger Nano S - Secure firmware + * (c) 2022 Ledger + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + ********************************************************************************/ /** * @file lcx_crc.h @@ -45,7 +45,7 @@ * * @return Current CRC value. */ - uint16_t cx_crc16(const void *buffer, size_t len); +uint16_t cx_crc16(const void *buffer, size_t len); /** * @brief Accumulates more data to CRC. @@ -58,8 +58,8 @@ * * @return Updated CRC value. */ - uint16_t cx_crc16_update(uint16_t crc, const void *buffer, size_t len); +uint16_t cx_crc16_update(uint16_t crc, const void *buffer, size_t len); #endif -#endif // HAVE_CRC +#endif // HAVE_CRC diff --git a/lib_cxng/include/lcx_ecdh.h b/lib_cxng/include/lcx_ecdh.h index 2b05f1013..77aaa6830 100644 --- a/lib_cxng/include/lcx_ecdh.h +++ b/lib_cxng/include/lcx_ecdh.h @@ -1,20 +1,20 @@ /******************************************************************************* -* Ledger Nano S - Secure firmware -* (c) 2022 Ledger -* -* Licensed under the Apache License, Version 2.0 (the "License"); -* you may not use this file except in compliance with the License. -* You may obtain a copy of the License at -* -* http://www.apache.org/licenses/LICENSE-2.0 -* -* Unless required by applicable law or agreed to in writing, software -* distributed under the License is distributed on an "AS IS" BASIS, -* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -* See the License for the specific language governing permissions and -* limitations under the License. -********************************************************************************/ + * Ledger Nano S - Secure firmware + * (c) 2022 Ledger + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + ********************************************************************************/ /** * @file lcx_ecdh.h @@ -73,31 +73,37 @@ * - CX_EC_INFINITE_POINT */ cx_err_t cx_ecdh_no_throw(const cx_ecfp_private_key_t *pvkey, - uint32_t mode, - const uint8_t * P, - size_t P_len, - uint8_t * secret, - size_t secret_len); + uint32_t mode, + const uint8_t *P, + size_t P_len, + uint8_t *secret, + size_t secret_len); /** * @deprecated * See #cx_ecdh_no_throw */ -DEPRECATED static inline size_t cx_ecdh ( const cx_ecfp_private_key_t * pvkey, uint32_t mode, const unsigned char * P, unsigned int P_len, unsigned char * secret, unsigned int secret_len ) +DEPRECATED static inline size_t cx_ecdh(const cx_ecfp_private_key_t *pvkey, + uint32_t mode, + const unsigned char *P, + unsigned int P_len, + unsigned char *secret, + unsigned int secret_len) { - CX_THROW(cx_ecdh_no_throw(pvkey, mode, P, P_len, secret, secret_len)); + CX_THROW(cx_ecdh_no_throw(pvkey, mode, P, P_len, secret, secret_len)); - size_t size; + size_t size; - CX_THROW(cx_ecdomain_parameters_length(pvkey->curve, &size)); - if ((mode & CX_MASK_EC) == CX_ECDH_POINT) { - return 1 + 2 * size; - } else { - return size; - } + CX_THROW(cx_ecdomain_parameters_length(pvkey->curve, &size)); + if ((mode & CX_MASK_EC) == CX_ECDH_POINT) { + return 1 + 2 * size; + } + else { + return size; + } } -#endif // HAVE_ECDH +#endif // HAVE_ECDH #if defined(HAVE_X25519) /** @@ -127,7 +133,7 @@ DEPRECATED static inline size_t cx_ecdh ( const cx_ecfp_private_key_t * pvkey, u * - CX_INVALID_PARAMETER_VALUE */ cx_err_t cx_x25519(uint8_t *u, const uint8_t *k, size_t k_len); -#endif // HAVE_X25519 +#endif // HAVE_X25519 #if defined(HAVE_X448) /** @@ -157,10 +163,10 @@ cx_err_t cx_x25519(uint8_t *u, const uint8_t *k, size_t k_len); * - CX_INVALID_PARAMETER_VALUE */ cx_err_t cx_x448(uint8_t *u, const uint8_t *k, size_t k_len); -#endif // HAVE_X448 +#endif // HAVE_X448 -#endif // HAVE_ECDH || HAVE_X25519 || HAVE_X448 +#endif // HAVE_ECDH || HAVE_X25519 || HAVE_X448 -#endif // HAVE_ECDH +#endif // HAVE_ECDH -#endif // LCX_ECDH_H +#endif // LCX_ECDH_H diff --git a/lib_cxng/include/lcx_ecdsa.h b/lib_cxng/include/lcx_ecdsa.h index 5d2f33fe7..cd934a5aa 100644 --- a/lib_cxng/include/lcx_ecdsa.h +++ b/lib_cxng/include/lcx_ecdsa.h @@ -1,20 +1,20 @@ /******************************************************************************* -* Ledger Nano S - Secure firmware -* (c) 2022 Ledger -* -* Licensed under the Apache License, Version 2.0 (the "License"); -* you may not use this file except in compliance with the License. -* You may obtain a copy of the License at -* -* http://www.apache.org/licenses/LICENSE-2.0 -* -* Unless required by applicable law or agreed to in writing, software -* distributed under the License is distributed on an "AS IS" BASIS, -* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -* See the License for the specific language governing permissions and -* limitations under the License. -********************************************************************************/ + * Ledger Nano S - Secure firmware + * (c) 2022 Ledger + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + ********************************************************************************/ /** * @file lcx_ecdsa.h @@ -34,7 +34,7 @@ #include "lcx_ecfp.h" /** @internal Backward compatibility */ -#define cx_ecdsa_init_public_key cx_ecfp_init_public_key_no_throw +#define cx_ecdsa_init_public_key cx_ecfp_init_public_key_no_throw /** @internal Backward compatibility */ #define cx_ecdsa_init_private_key cx_ecfp_init_private_key_no_throw @@ -59,11 +59,13 @@ * @param[in] hash_len Length of the digest in octets. * * @param[out] sig Buffer where to store the signature. - * The signature is encoded in TLV: **30 || L || 02 || Lr || r || 02 || Ls || s** + * The signature is encoded in TLV: **30 || L || 02 || Lr || r || 02 || Ls || + * s** * * @param[in] sig_len Length of the buffer in octets. * - * @param[out] info Set with CX_ECCINFO_PARITY_ODD if the y-coordinate is odd when computing **[k].G**. + * @param[out] info Set with CX_ECCINFO_PARITY_ODD if the y-coordinate is odd when computing + * **[k].G**. * * @return Error code: * - CX_OK on success @@ -79,30 +81,36 @@ * - CX_INVALID_PARAMETER_VALUE */ cx_err_t cx_ecdsa_sign_no_throw(const cx_ecfp_private_key_t *pvkey, - uint32_t mode, - cx_md_t hashID, - const uint8_t * hash, - size_t hash_len, - uint8_t * sig, - size_t * sig_len, - uint32_t * info); + uint32_t mode, + cx_md_t hashID, + const uint8_t *hash, + size_t hash_len, + uint8_t *sig, + size_t *sig_len, + uint32_t *info); /** * @deprecated * See #cx_ecdsa_sign_no_throw */ -DEPRECATED static inline size_t cx_ecdsa_sign ( const cx_ecfp_private_key_t * pvkey, uint32_t mode, cx_md_t hashID, const unsigned char * hash, unsigned int hash_len, unsigned char * sig, unsigned int sig_len, unsigned int * info ) +DEPRECATED static inline size_t cx_ecdsa_sign(const cx_ecfp_private_key_t *pvkey, + uint32_t mode, + cx_md_t hashID, + const unsigned char *hash, + unsigned int hash_len, + unsigned char *sig, + unsigned int sig_len, + unsigned int *info) { - size_t sig_len_ = sig_len; - uint32_t info_; - CX_THROW(cx_ecdsa_sign_no_throw(pvkey, mode, hashID, hash, hash_len, sig, &sig_len_, &info_)); - if (info) { - *info = (uint32_t)info_; - } - return sig_len_; + size_t sig_len_ = sig_len; + uint32_t info_; + CX_THROW(cx_ecdsa_sign_no_throw(pvkey, mode, hashID, hash, hash_len, sig, &sig_len_, &info_)); + if (info) { + *info = (uint32_t) info_; + } + return sig_len_; } - /** * @brief Verifies an ECDSA signature according to ECDSA specification. * @@ -114,17 +122,18 @@ DEPRECATED static inline size_t cx_ecdsa_sign ( const cx_ecfp_private_key_t * pv * * @param[in] hash_len Length of the digest in octets. * - * @param[in] sig Pointer to the signature encoded in TLV: **30 || L || 02 || Lr || r || 02 || Ls || s** + * @param[in] sig Pointer to the signature encoded in TLV: **30 || L || 02 || Lr || r || 02 || + * Ls || s** * * @param[in] sig_len Length of the signature in octets. * * @return 1 if the signature is verified, 0 otherwise. */ bool cx_ecdsa_verify_no_throw(const cx_ecfp_public_key_t *pukey, - const uint8_t * hash, - size_t hash_len, - const uint8_t * sig, - size_t sig_len); + const uint8_t *hash, + size_t hash_len, + const uint8_t *sig, + size_t sig_len); /** * @brief Verifies an ECDSA signature according to ECDSA specification. @@ -142,20 +151,26 @@ bool cx_ecdsa_verify_no_throw(const cx_ecfp_public_key_t *pukey, * * @param[in] hash_len Length of the digest in octets. * - * @param[in] sig Pointer to the signature encoded in TLV: **30 || L || 02 || Lr || r || 02 || Ls || s** + * @param[in] sig Pointer to the signature encoded in TLV: **30 || L || 02 || Lr || r || 02 || + * Ls || s** * * @param[in] sig_len Length of the signature in octets. * * @return 1 if the signature is verified, 0 otherwise. */ -static inline bool cx_ecdsa_verify ( const cx_ecfp_public_key_t * pukey, int mode, cx_md_t hashID, const unsigned char * hash, unsigned int hash_len, const unsigned char * sig, unsigned int sig_len) +static inline bool cx_ecdsa_verify(const cx_ecfp_public_key_t *pukey, + int mode, + cx_md_t hashID, + const unsigned char *hash, + unsigned int hash_len, + const unsigned char *sig, + unsigned int sig_len) { - UNUSED(mode); - UNUSED(hashID); - return cx_ecdsa_verify_no_throw(pukey, hash, hash_len, sig, sig_len); + UNUSED(mode); + UNUSED(hashID); + return cx_ecdsa_verify_no_throw(pukey, hash, hash_len, sig, sig_len); } - #endif -#endif // HAVE_ECDSA +#endif // HAVE_ECDSA diff --git a/lib_cxng/include/lcx_ecfp.h b/lib_cxng/include/lcx_ecfp.h index baea20172..0c8941e22 100644 --- a/lib_cxng/include/lcx_ecfp.h +++ b/lib_cxng/include/lcx_ecfp.h @@ -1,20 +1,20 @@ /******************************************************************************* -* Ledger Nano S - Secure firmware -* (c) 2022 Ledger -* -* Licensed under the Apache License, Version 2.0 (the "License"); -* you may not use this file except in compliance with the License. -* You may obtain a copy of the License at -* -* http://www.apache.org/licenses/LICENSE-2.0 -* -* Unless required by applicable law or agreed to in writing, software -* distributed under the License is distributed on an "AS IS" BASIS, -* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -* See the License for the specific language governing permissions and -* limitations under the License. -********************************************************************************/ + * Ledger Nano S - Secure firmware + * (c) 2022 Ledger + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + ********************************************************************************/ /** * @file lcx_ecfp.h @@ -23,7 +23,6 @@ * Private and public keys initialization and key pair generation based on elliptic curves. */ - #ifdef HAVE_ECC #ifndef LCX_ECFP_H #define LCX_ECFP_H @@ -35,35 +34,35 @@ /** Elliptic Curve public key */ struct cx_ecfp_public_key_s { - cx_curve_t curve; ///< Curve identifier - size_t W_len; ///< Public key length in bytes - uint8_t W[1]; ///< Public key value + cx_curve_t curve; ///< Curve identifier + size_t W_len; ///< Public key length in bytes + uint8_t W[1]; ///< Public key value }; /** Elliptic Curve private key */ struct cx_ecfp_private_key_s { - cx_curve_t curve; ///< Curve identifier - size_t d_len; ///< Private key length in bytes - uint8_t d[1]; ///< Private key value + cx_curve_t curve; ///< Curve identifier + size_t d_len; ///< Private key length in bytes + uint8_t d[1]; ///< Private key value }; /** Up to 256-bit Elliptic Curve public key */ struct cx_ecfp_256_public_key_s { - cx_curve_t curve; ///< Curve identifier - size_t W_len; ///< Public key length in bytes - uint8_t W[65]; ///< Public key value + cx_curve_t curve; ///< Curve identifier + size_t W_len; ///< Public key length in bytes + uint8_t W[65]; ///< Public key value }; /** Up to 256-bit Elliptic Curve private key */ struct cx_ecfp_256_private_key_s { - cx_curve_t curve; ///< Curve identifier - size_t d_len; ///< Private key length in bytes - uint8_t d[32]; ///< Private key value + cx_curve_t curve; ///< Curve identifier + size_t d_len; ///< Private key length in bytes + uint8_t d[32]; ///< Private key value }; /** Up to 256-bit Elliptic Curve extended private key */ struct cx_ecfp_256_extended_private_key_s { - cx_curve_t curve; ///< Curve identifier - size_t d_len; ///< Public key length in bytes - uint8_t d[64]; ///< Public key value + cx_curve_t curve; ///< Curve identifier + size_t d_len; ///< Public key length in bytes + uint8_t d[64]; ///< Public key value }; /** Convenience type. See #cx_ecfp_256_public_key_s. */ typedef struct cx_ecfp_256_public_key_s cx_ecfp_256_public_key_t; @@ -78,15 +77,15 @@ typedef struct cx_ecfp_256_private_key_s cx_ecfp_private_key_t; /** Up to 384-bit Elliptic Curve public key */ struct cx_ecfp_384_public_key_s { - cx_curve_t curve; ///< Curve identifier - size_t W_len; ///< Public key length in bytes - uint8_t W[97]; ///< Public key value + cx_curve_t curve; ///< Curve identifier + size_t W_len; ///< Public key length in bytes + uint8_t W[97]; ///< Public key value }; /** Up to 384-bit Elliptic Curve private key */ struct cx_ecfp_384_private_key_s { - cx_curve_t curve; ///< Curve identifier - size_t d_len; ///< Private key length in bytes - uint8_t d[48]; ///< Private key value + cx_curve_t curve; ///< Curve identifier + size_t d_len; ///< Private key length in bytes + uint8_t d[48]; ///< Private key value }; /** Convenience type. See #cx_ecfp_384_public_key_s. */ typedef struct cx_ecfp_384_private_key_s cx_ecfp_384_private_key_t; @@ -95,21 +94,21 @@ typedef struct cx_ecfp_384_public_key_s cx_ecfp_384_public_key_t; /** Up to 512-bit Elliptic Curve public key */ struct cx_ecfp_512_public_key_s { - cx_curve_t curve; ///< Curve identifier - size_t W_len; ///< Public key length in bytes - uint8_t W[129]; ///< Public key value + cx_curve_t curve; ///< Curve identifier + size_t W_len; ///< Public key length in bytes + uint8_t W[129]; ///< Public key value }; /** Up to 512-bit Elliptic Curve private key */ struct cx_ecfp_512_private_key_s { - cx_curve_t curve; ///< Curve identifier - size_t d_len; ///< Private key length in bytes - uint8_t d[64]; ///< Private key value + cx_curve_t curve; ///< Curve identifier + size_t d_len; ///< Private key length in bytes + uint8_t d[64]; ///< Private key value }; /** Up to 512-bit Elliptic Curve extended private key */ struct cx_ecfp_512_extented_private_key_s { - cx_curve_t curve; ///< Curve identifier - size_t d_len; ///< Private key length in bytes - uint8_t d[128]; ///< Private key value + cx_curve_t curve; ///< Curve identifier + size_t d_len; ///< Private key length in bytes + uint8_t d[128]; ///< Private key value }; /** Convenience type. See #cx_ecfp_512_public_key_s. */ typedef struct cx_ecfp_512_public_key_s cx_ecfp_512_public_key_t; @@ -120,15 +119,15 @@ typedef struct cx_ecfp_512_extented_private_key_s cx_ecfp_512_extented_private_k /** Up to 640-bit Elliptic Curve public key */ struct cx_ecfp_640_public_key_s { - cx_curve_t curve; ///< Curve identifier - size_t W_len; ///< Public key length in bytes - uint8_t W[161]; ///< Public key value + cx_curve_t curve; ///< Curve identifier + size_t W_len; ///< Public key length in bytes + uint8_t W[161]; ///< Public key value }; /** Up to 640-bit Elliptic Curve private key */ struct cx_ecfp_640_private_key_s { - cx_curve_t curve; ///< Curve identifier - size_t d_len; ///< Private key length in bytes - uint8_t d[80]; ///< Private key value + cx_curve_t curve; ///< Curve identifier + size_t d_len; ///< Private key length in bytes + uint8_t d[80]; ///< Private key value }; /** Convenience type. See #cx_ecfp_640_public_key_s. */ typedef struct cx_ecfp_640_public_key_s cx_ecfp_640_public_key_t; @@ -160,22 +159,29 @@ typedef struct cx_ecfp_640_private_key_s cx_ecfp_640_private_key_t; * - CX_EC_INVALID_POINT * - CX_EC_INFINITE_POINT */ -cx_err_t cx_ecfp_add_point_no_throw(cx_curve_t curve, uint8_t *R, const uint8_t *P, const uint8_t *Q); +cx_err_t cx_ecfp_add_point_no_throw(cx_curve_t curve, + uint8_t *R, + const uint8_t *P, + const uint8_t *Q); /** * @deprecated * See #cx_ecfp_add_point_no_throw */ -DEPRECATED static inline size_t cx_ecfp_add_point ( cx_curve_t curve, unsigned char * R, const unsigned char * P, const unsigned char * Q, unsigned int X_len ) +DEPRECATED static inline size_t cx_ecfp_add_point(cx_curve_t curve, + unsigned char *R, + const unsigned char *P, + const unsigned char *Q, + unsigned int X_len) { - UNUSED(X_len); + UNUSED(X_len); - CX_THROW(cx_ecfp_add_point_no_throw(curve, R, P, Q)); + CX_THROW(cx_ecfp_add_point_no_throw(curve, R, P, Q)); - size_t size; - CX_THROW(cx_ecdomain_parameters_length(curve, &size)); + size_t size; + CX_THROW(cx_ecdomain_parameters_length(curve, &size)); - return 1 + 2 * size; + return 1 + 2 * size; } /** @@ -209,16 +215,20 @@ cx_err_t cx_ecfp_scalar_mult_no_throw(cx_curve_t curve, uint8_t *P, const uint8_ * @deprecated * See #cx_ecfp_scalar_mult_no_throw */ -DEPRECATED static inline size_t cx_ecfp_scalar_mult ( cx_curve_t curve, unsigned char * P, unsigned int P_len, const unsigned char * k, unsigned int k_len ) +DEPRECATED static inline size_t cx_ecfp_scalar_mult(cx_curve_t curve, + unsigned char *P, + unsigned int P_len, + const unsigned char *k, + unsigned int k_len) { - UNUSED(P_len); + UNUSED(P_len); - CX_THROW(cx_ecfp_scalar_mult_no_throw(curve, P, k, k_len)); + CX_THROW(cx_ecfp_scalar_mult_no_throw(curve, P, k, k_len)); - size_t size; - CX_THROW(cx_ecdomain_parameters_length(curve, &size)); + size_t size; + CX_THROW(cx_ecdomain_parameters_length(curve, &size)); - return 1 + 2 * size; + return 1 + 2 * size; } /** @@ -245,18 +255,21 @@ DEPRECATED static inline size_t cx_ecfp_scalar_mult ( cx_curve_t curve, unsigned * - INVALID_PARAMETER */ cx_err_t cx_ecfp_init_public_key_no_throw(cx_curve_t curve, - const uint8_t * rawkey, - size_t key_len, - cx_ecfp_public_key_t *key); + const uint8_t *rawkey, + size_t key_len, + cx_ecfp_public_key_t *key); /** * @deprecated * See #cx_ecfp_init_public_key_no_throw */ -DEPRECATED static inline size_t cx_ecfp_init_public_key ( cx_curve_t curve, const unsigned char * rawkey, unsigned int key_len, cx_ecfp_public_key_t * key ) +DEPRECATED static inline size_t cx_ecfp_init_public_key(cx_curve_t curve, + const unsigned char *rawkey, + unsigned int key_len, + cx_ecfp_public_key_t *key) { - CX_THROW(cx_ecfp_init_public_key_no_throw(curve, rawkey, key_len, key)); - return key_len; + CX_THROW(cx_ecfp_init_public_key_no_throw(curve, rawkey, key_len, key)); + return key_len; } /** @@ -280,18 +293,21 @@ DEPRECATED static inline size_t cx_ecfp_init_public_key ( cx_curve_t curve, cons * - CX_INVALID_PARAMETER */ cx_err_t cx_ecfp_init_private_key_no_throw(cx_curve_t curve, - const uint8_t * rawkey, - size_t key_len, - cx_ecfp_private_key_t *pvkey); + const uint8_t *rawkey, + size_t key_len, + cx_ecfp_private_key_t *pvkey); /** * @deprecated * See #cx_ecfp_init_private_key_no_throw */ -DEPRECATED static inline size_t cx_ecfp_init_private_key ( cx_curve_t curve, const unsigned char * rawkey, size_t key_len, cx_ecfp_private_key_t * pvkey ) +DEPRECATED static inline size_t cx_ecfp_init_private_key(cx_curve_t curve, + const unsigned char *rawkey, + size_t key_len, + cx_ecfp_private_key_t *pvkey) { - CX_THROW(cx_ecfp_init_private_key_no_throw(curve, rawkey, key_len, pvkey)); - return key_len; + CX_THROW(cx_ecfp_init_private_key_no_throw(curve, rawkey, key_len, pvkey)); + return key_len; } /** @@ -320,18 +336,21 @@ DEPRECATED static inline size_t cx_ecfp_init_private_key ( cx_curve_t curve, con * - CX_EC_INFINITE_POINT */ cx_err_t cx_ecfp_generate_pair_no_throw(cx_curve_t curve, - cx_ecfp_public_key_t * pubkey, - cx_ecfp_private_key_t *privkey, - bool keepprivate); + cx_ecfp_public_key_t *pubkey, + cx_ecfp_private_key_t *privkey, + bool keepprivate); /** * @deprecated * See #cx_ecfp_generate_pair_no_throw */ -DEPRECATED static inline int cx_ecfp_generate_pair ( cx_curve_t curve, cx_ecfp_public_key_t * pubkey, cx_ecfp_private_key_t * privkey, int keepprivate ) +DEPRECATED static inline int cx_ecfp_generate_pair(cx_curve_t curve, + cx_ecfp_public_key_t *pubkey, + cx_ecfp_private_key_t *privkey, + int keepprivate) { - CX_THROW(cx_ecfp_generate_pair_no_throw(curve, pubkey, privkey, keepprivate)); - return 0; + CX_THROW(cx_ecfp_generate_pair_no_throw(curve, pubkey, privkey, keepprivate)); + return 0; } /** @@ -362,19 +381,23 @@ DEPRECATED static inline int cx_ecfp_generate_pair ( cx_curve_t curve, cx_ecfp_p * - CX_EC_INFINITE_POINT */ cx_err_t cx_ecfp_generate_pair2_no_throw(cx_curve_t curve, - cx_ecfp_public_key_t * pubkey, - cx_ecfp_private_key_t *privkey, - bool keepprivate, - cx_md_t hashID); + cx_ecfp_public_key_t *pubkey, + cx_ecfp_private_key_t *privkey, + bool keepprivate, + cx_md_t hashID); /** * @deprecated * See #cx_ecfp_generate_pair2_no_throw */ -DEPRECATED static inline int cx_ecfp_generate_pair2 ( cx_curve_t curve, cx_ecfp_public_key_t * pubkey, cx_ecfp_private_key_t * privkey, int keepprivate, cx_md_t hashID ) +DEPRECATED static inline int cx_ecfp_generate_pair2(cx_curve_t curve, + cx_ecfp_public_key_t *pubkey, + cx_ecfp_private_key_t *privkey, + int keepprivate, + cx_md_t hashID) { - CX_THROW(cx_ecfp_generate_pair2_no_throw(curve, pubkey, privkey, keepprivate, hashID)); - return 0; + CX_THROW(cx_ecfp_generate_pair2_no_throw(curve, pubkey, privkey, keepprivate, hashID)); + return 0; } #ifdef HAVE_ECC_TWISTED_EDWARDS @@ -414,20 +437,26 @@ DEPRECATED static inline int cx_ecfp_generate_pair2 ( cx_curve_t curve, cx_ecfp_ * */ cx_err_t cx_eddsa_get_public_key_no_throw(const cx_ecfp_private_key_t *pvkey, - cx_md_t hashID, - cx_ecfp_public_key_t * pukey, - uint8_t * a, - size_t a_len, - uint8_t * h, - size_t h_len); + cx_md_t hashID, + cx_ecfp_public_key_t *pukey, + uint8_t *a, + size_t a_len, + uint8_t *h, + size_t h_len); /** * @deprecated * See #cx_eddsa_get_public_key_no_throw */ -DEPRECATED static inline void cx_eddsa_get_public_key ( const cx_ecfp_private_key_t * pvkey, cx_md_t hashID, cx_ecfp_public_key_t * pukey, unsigned char * a, unsigned int a_len, unsigned char * h, unsigned int h_len ) +DEPRECATED static inline void cx_eddsa_get_public_key(const cx_ecfp_private_key_t *pvkey, + cx_md_t hashID, + cx_ecfp_public_key_t *pukey, + unsigned char *a, + unsigned int a_len, + unsigned char *h, + unsigned int h_len) { - CX_THROW(cx_eddsa_get_public_key_no_throw(pvkey, hashID, pukey, a, a_len, h, h_len)); + CX_THROW(cx_eddsa_get_public_key_no_throw(pvkey, hashID, pukey, a, a_len, h, h_len)); } /** @@ -460,7 +489,7 @@ cx_err_t cx_edwards_compress_point_no_throw(cx_curve_t curve, uint8_t *p, size_t */ DEPRECATED static inline void cx_edwards_compress_point(cx_curve_t curve, uint8_t *p, size_t p_len) { - CX_THROW(cx_edwards_compress_point_no_throw(curve, p, p_len)); + CX_THROW(cx_edwards_compress_point_no_throw(curve, p, p_len)); } /** @@ -493,29 +522,33 @@ cx_err_t cx_edwards_decompress_point_no_throw(cx_curve_t curve, uint8_t *p, size * @deprecated * See #cx_edwards_decompress_point_no_throw */ -DEPRECATED static inline void cx_edwards_decompress_point(cx_curve_t curve, uint8_t *p, size_t p_len) +DEPRECATED static inline void cx_edwards_decompress_point(cx_curve_t curve, + uint8_t *p, + size_t p_len) { - CX_THROW(cx_edwards_decompress_point_no_throw(curve, p, p_len)); + CX_THROW(cx_edwards_decompress_point_no_throw(curve, p, p_len)); } /** * @deprecated * See #cx_edwards_compress_point_no_throw */ -DEPRECATED static inline void cx_edward_compress_point(cx_curve_t curve, uint8_t *p, size_t p_len) { - CX_THROW(cx_edwards_compress_point_no_throw(curve, p, p_len)); +DEPRECATED static inline void cx_edward_compress_point(cx_curve_t curve, uint8_t *p, size_t p_len) +{ + CX_THROW(cx_edwards_compress_point_no_throw(curve, p, p_len)); } /** * @deprecated * See #cx_edwards_decompress_point_no_throw */ -DEPRECATED static inline void cx_edward_decompress_point(cx_curve_t curve, uint8_t *p, size_t p_len) { - CX_THROW(cx_edwards_decompress_point_no_throw(curve, p, p_len)); +DEPRECATED static inline void cx_edward_decompress_point(cx_curve_t curve, uint8_t *p, size_t p_len) +{ + CX_THROW(cx_edwards_decompress_point_no_throw(curve, p, p_len)); } -#endif // HAVE_ECC_TWISTED_EDWARDS +#endif // HAVE_ECC_TWISTED_EDWARDS #endif -#endif // HAVE_ECC +#endif // HAVE_ECC diff --git a/lib_cxng/include/lcx_ecschnorr.h b/lib_cxng/include/lcx_ecschnorr.h index a26b7439c..719cc45b4 100644 --- a/lib_cxng/include/lcx_ecschnorr.h +++ b/lib_cxng/include/lcx_ecschnorr.h @@ -1,20 +1,20 @@ /******************************************************************************* -* Ledger Nano S - Secure firmware -* (c) 2022 Ledger -* -* Licensed under the Apache License, Version 2.0 (the "License"); -* you may not use this file except in compliance with the License. -* You may obtain a copy of the License at -* -* http://www.apache.org/licenses/LICENSE-2.0 -* -* Unless required by applicable law or agreed to in writing, software -* distributed under the License is distributed on an "AS IS" BASIS, -* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -* See the License for the specific language governing permissions and -* limitations under the License. -********************************************************************************/ + * Ledger Nano S - Secure firmware + * (c) 2022 Ledger + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + ********************************************************************************/ /** * @file lcx_ecschnorr.h @@ -54,8 +54,8 @@ * * @param[in] msg_len Length of input data. * - * @param[out] sig ECSchnorr signature encoded in TLV: **30 || L || 02 || Lr || r || 02 || Ls || s**. - * This parameter holds the auxiliary random data when CX_ECSCHNORR_BIP0340 is used. + * @param[out] sig ECSchnorr signature encoded in TLV: **30 || L || 02 || Lr || r || 02 || Ls || + * s**. This parameter holds the auxiliary random data when CX_ECSCHNORR_BIP0340 is used. * * @param[in] sig_len Length of the signature. * @@ -72,22 +72,29 @@ * - CX_INVALID_PARAMETER_VALUE */ cx_err_t cx_ecschnorr_sign_no_throw(const cx_ecfp_private_key_t *pvkey, - uint32_t mode, - cx_md_t hashID, - const uint8_t * msg, - size_t msg_len, - uint8_t * sig, - size_t * sig_len); + uint32_t mode, + cx_md_t hashID, + const uint8_t *msg, + size_t msg_len, + uint8_t *sig, + size_t *sig_len); /** * @deprecated * See #cx_ecschnorr_sign_no_throw */ -DEPRECATED static inline size_t cx_ecschnorr_sign ( const cx_ecfp_private_key_t * pvkey, uint32_t mode, cx_md_t hashID, const unsigned char * msg, unsigned int msg_len, unsigned char * sig, size_t sig_len, unsigned int * info ) +DEPRECATED static inline size_t cx_ecschnorr_sign(const cx_ecfp_private_key_t *pvkey, + uint32_t mode, + cx_md_t hashID, + const unsigned char *msg, + unsigned int msg_len, + unsigned char *sig, + size_t sig_len, + unsigned int *info) { - UNUSED(info); - CX_THROW(cx_ecschnorr_sign_no_throw(pvkey, mode, hashID, msg, msg_len, sig, &sig_len)); - return sig_len; + UNUSED(info); + CX_THROW(cx_ecschnorr_sign_no_throw(pvkey, mode, hashID, msg, msg_len, sig, &sig_len)); + return sig_len; } /** @@ -124,11 +131,11 @@ DEPRECATED static inline size_t cx_ecschnorr_sign ( const cx_ecfp_private_key_t bool cx_ecschnorr_verify(const cx_ecfp_public_key_t *pukey, uint32_t mode, cx_md_t hashID, - const uint8_t * msg, + const uint8_t *msg, size_t msg_len, - const uint8_t * sig, + const uint8_t *sig, size_t sig_len); #endif -#endif // HAVE_ECSHCNORR +#endif // HAVE_ECSHCNORR diff --git a/lib_cxng/include/lcx_eddsa.h b/lib_cxng/include/lcx_eddsa.h index 83e390574..b9212693b 100644 --- a/lib_cxng/include/lcx_eddsa.h +++ b/lib_cxng/include/lcx_eddsa.h @@ -1,20 +1,20 @@ /******************************************************************************* -* Ledger Nano S - Secure firmware -* (c) 2022 Ledger -* -* Licensed under the Apache License, Version 2.0 (the "License"); -* you may not use this file except in compliance with the License. -* You may obtain a copy of the License at -* -* http://www.apache.org/licenses/LICENSE-2.0 -* -* Unless required by applicable law or agreed to in writing, software -* distributed under the License is distributed on an "AS IS" BASIS, -* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -* See the License for the specific language governing permissions and -* limitations under the License. -********************************************************************************/ + * Ledger Nano S - Secure firmware + * (c) 2022 Ledger + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + ********************************************************************************/ /** * @file lcx_eddsa.h @@ -72,29 +72,38 @@ * - CX_INVALID_PARAMETER_VALUE */ cx_err_t cx_eddsa_sign_no_throw(const cx_ecfp_private_key_t *pvkey, - cx_md_t hashID, - const uint8_t * hash, - size_t hash_len, - uint8_t * sig, - size_t sig_len); + cx_md_t hashID, + const uint8_t *hash, + size_t hash_len, + uint8_t *sig, + size_t sig_len); /** * @deprecated * See #cx_eddsa_sign_no_throw */ -DEPRECATED static inline size_t cx_eddsa_sign ( const cx_ecfp_private_key_t * pvkey, int mode, cx_md_t hashID, const unsigned char * hash, unsigned int hash_len, const unsigned char * ctx, unsigned int ctx_len, unsigned char * sig, unsigned int sig_len, unsigned int * info ) +DEPRECATED static inline size_t cx_eddsa_sign(const cx_ecfp_private_key_t *pvkey, + int mode, + cx_md_t hashID, + const unsigned char *hash, + unsigned int hash_len, + const unsigned char *ctx, + unsigned int ctx_len, + unsigned char *sig, + unsigned int sig_len, + unsigned int *info) { - UNUSED(ctx); - UNUSED(ctx_len); - UNUSED(mode); - UNUSED(info); + UNUSED(ctx); + UNUSED(ctx_len); + UNUSED(mode); + UNUSED(info); - CX_THROW(cx_eddsa_sign_no_throw(pvkey, hashID, hash, hash_len, sig, sig_len)); + CX_THROW(cx_eddsa_sign_no_throw(pvkey, hashID, hash, hash_len, sig, sig_len)); - size_t size; - CX_THROW(cx_ecdomain_parameters_length(pvkey->curve, &size)); + size_t size; + CX_THROW(cx_ecdomain_parameters_length(pvkey->curve, &size)); - return 2 * size; + return 2 * size; } /** @@ -123,11 +132,11 @@ DEPRECATED static inline size_t cx_eddsa_sign ( const cx_ecfp_private_key_t * pv * @return 1 if the signature is verified, otherwise 0. */ bool cx_eddsa_verify_no_throw(const cx_ecfp_public_key_t *pukey, - cx_md_t hashID, - const uint8_t * hash, - size_t hash_len, - const uint8_t * sig, - size_t sig_len); + cx_md_t hashID, + const uint8_t *hash, + size_t hash_len, + const uint8_t *sig, + size_t sig_len); /** * @brief Verifies a signature. @@ -162,16 +171,23 @@ bool cx_eddsa_verify_no_throw(const cx_ecfp_public_key_t *pukey, * * @return 1 if the signature is verified, otherwise 0. */ -static inline int cx_eddsa_verify ( const cx_ecfp_public_key_t * pukey, int mode, cx_md_t hashID, const unsigned char * hash, unsigned int hash_len, const unsigned char * ctx, unsigned int ctx_len, const unsigned char * sig, unsigned int sig_len ) +static inline int cx_eddsa_verify(const cx_ecfp_public_key_t *pukey, + int mode, + cx_md_t hashID, + const unsigned char *hash, + unsigned int hash_len, + const unsigned char *ctx, + unsigned int ctx_len, + const unsigned char *sig, + unsigned int sig_len) { - UNUSED(mode); - UNUSED(ctx); - UNUSED(ctx_len); + UNUSED(mode); + UNUSED(ctx); + UNUSED(ctx_len); - return cx_eddsa_verify_no_throw(pukey, hashID, hash, hash_len, sig, sig_len); + return cx_eddsa_verify_no_throw(pukey, hashID, hash, hash_len, sig, sig_len); } - /** * @brief Encodes the curve point coordinates. * @@ -182,9 +198,7 @@ static inline int cx_eddsa_verify ( const cx_ecfp_public_key_t * pukey, int mode * @param[in] sign Sign of the x-coordinate. * */ - void cx_encode_coord(uint8_t * coord, - int len, - int sign); +void cx_encode_coord(uint8_t *coord, int len, int sign); /** * @brief Decodes the curve point coordinates. @@ -195,9 +209,8 @@ static inline int cx_eddsa_verify ( const cx_ecfp_public_key_t * pukey, int mode * * @return Sign of the x-coordinate. */ - int cx_decode_coord(uint8_t * coord, - int len); +int cx_decode_coord(uint8_t *coord, int len); #endif -#endif // HAVE_EDDSA +#endif // HAVE_EDDSA diff --git a/lib_cxng/include/lcx_groestl.h b/lib_cxng/include/lcx_groestl.h index 0547ca2eb..f190d78e5 100644 --- a/lib_cxng/include/lcx_groestl.h +++ b/lib_cxng/include/lcx_groestl.h @@ -1,20 +1,20 @@ /******************************************************************************* -* Ledger Nano S - Secure firmware -* (c) 2022 Ledger -* -* Licensed under the Apache License, Version 2.0 (the "License"); -* you may not use this file except in compliance with the License. -* You may obtain a copy of the License at -* -* http://www.apache.org/licenses/LICENSE-2.0 -* -* Unless required by applicable law or agreed to in writing, software -* distributed under the License is distributed on an "AS IS" BASIS, -* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -* See the License for the specific language governing permissions and -* limitations under the License. -********************************************************************************/ + * Ledger Nano S - Secure firmware + * (c) 2022 Ledger + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + ********************************************************************************/ /** * @file lcx_groestl.h @@ -32,20 +32,20 @@ #include "lcx_wrappers.h" -#define ROWS 8 +#define ROWS 8 #define COLS1024 16 #define SIZE1024 (ROWS * COLS1024) typedef unsigned char BitSequence; /** @private Hash state */ struct hashState_s { - uint8_t chaining[ROWS][COLS1024]; ///< Actual state - uint64_t block_counter; ///< Block counter - unsigned int hashlen; ///< Output length - BitSequence buffer[SIZE1024]; ///< Block buffer - unsigned int buf_ptr; ///< Buffer pointer - unsigned int columns; ///< Number of columns in a state - unsigned int rounds; ///< Number of rounds in P and Q - unsigned int statesize; ///< Size of the state + uint8_t chaining[ROWS][COLS1024]; ///< Actual state + uint64_t block_counter; ///< Block counter + unsigned int hashlen; ///< Output length + BitSequence buffer[SIZE1024]; ///< Block buffer + unsigned int buf_ptr; ///< Buffer pointer + unsigned int columns; ///< Number of columns in a state + unsigned int rounds; ///< Number of rounds in P and Q + unsigned int statesize; ///< Size of the state }; /** @private */ typedef struct hashState_s hashState; @@ -54,8 +54,8 @@ typedef struct hashState_s hashState; * @brief Groestl context */ struct cx_groestl_s { - unsigned int output_size; ///< Output digest size - struct hashState_s ctx; ///< Hash state + unsigned int output_size; ///< Output digest size + struct hashState_s ctx; ///< Hash state }; /** Convenience type.*/ typedef struct cx_groestl_s cx_groestl_t; @@ -73,15 +73,15 @@ size_t cx_groestl_get_output_size(const cx_groestl_t *ctx); * - CX_OK on success * - CX_INVALID_PARAMETER */ - cx_err_t cx_groestl_init_no_throw(cx_groestl_t *hash, size_t size); +cx_err_t cx_groestl_init_no_throw(cx_groestl_t *hash, size_t size); /** * @deprecated * See #cx_groestl_init_no_throw */ -DEPRECATED static inline void cx_groestl_init ( cx_groestl_t * hash, unsigned int size ) +DEPRECATED static inline void cx_groestl_init(cx_groestl_t *hash, unsigned int size) { - CX_THROW(cx_groestl_init_no_throw(hash, size)); + CX_THROW(cx_groestl_init_no_throw(hash, size)); } /** @@ -111,7 +111,12 @@ DEPRECATED static inline void cx_groestl_init ( cx_groestl_t * hash, unsigned in * - CX_OK on success * - CX_INVALID_PARAMETER */ -cx_err_t cx_groestl(cx_groestl_t *hash, uint32_t mode, const uint8_t *in, size_t len, uint8_t *out, size_t out_len); +cx_err_t cx_groestl(cx_groestl_t *hash, + uint32_t mode, + const uint8_t *in, + size_t len, + uint8_t *out, + size_t out_len); /** * @brief Adds more data to hash. @@ -148,4 +153,4 @@ cx_err_t cx_groestl_final(cx_groestl_t *ctx, uint8_t *digest); #endif -#endif // HAVE_GROESTL +#endif // HAVE_GROESTL diff --git a/lib_cxng/include/lcx_hash.h b/lib_cxng/include/lcx_hash.h index 5ef8ea856..d05098366 100644 --- a/lib_cxng/include/lcx_hash.h +++ b/lib_cxng/include/lcx_hash.h @@ -1,20 +1,20 @@ /******************************************************************************* -* Ledger Nano S - Secure firmware -* (c) 2022 Ledger -* -* Licensed under the Apache License, Version 2.0 (the "License"); -* you may not use this file except in compliance with the License. -* You may obtain a copy of the License at -* -* http://www.apache.org/licenses/LICENSE-2.0 -* -* Unless required by applicable law or agreed to in writing, software -* distributed under the License is distributed on an "AS IS" BASIS, -* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -* See the License for the specific language governing permissions and -* limitations under the License. -********************************************************************************/ + * Ledger Nano S - Secure firmware + * (c) 2022 Ledger + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + ********************************************************************************/ /** * @file lcx_hash.h @@ -50,29 +50,29 @@ /** Message digest algorithm identifiers. */ enum cx_md_e { - CX_NONE = 0, ///< No message digest algorithm - // 20 bytes - CX_RIPEMD160 = 1, ///< RIPEMD160 digest - // 28 bytes - CX_SHA224 = 2, ///< SHA224 digest - // 32 bytes - CX_SHA256 = 3, ///< SHA256 digest - // 48 bytes - CX_SHA384 = 4, ///< SHA384 digest - // 64 bytes - CX_SHA512 = 5, ///< SHA512 digest - // 28,32,48,64 bytes - CX_KECCAK = 6, ///< Keccak (pre-SHA3) digest - // 28,32,48,64 bytes - CX_SHA3 = 7, ///< SHA3 Digest - DEPRECATED_0 = 8, ///< Keep compatibility - CX_BLAKE2B = 9, ///< Blake digest - // any bytes - CX_SHAKE128 = 10, ///< SHAKE-128 digest - // any bytes - CX_SHAKE256 = 11, ///< SHAKE-256 digest - CX_SHA3_256 = 12, ///< SHA3-256 digest - CX_SHA3_512 = 13, ///< SHA3-512 digest + CX_NONE = 0, ///< No message digest algorithm + // 20 bytes + CX_RIPEMD160 = 1, ///< RIPEMD160 digest + // 28 bytes + CX_SHA224 = 2, ///< SHA224 digest + // 32 bytes + CX_SHA256 = 3, ///< SHA256 digest + // 48 bytes + CX_SHA384 = 4, ///< SHA384 digest + // 64 bytes + CX_SHA512 = 5, ///< SHA512 digest + // 28,32,48,64 bytes + CX_KECCAK = 6, ///< Keccak (pre-SHA3) digest + // 28,32,48,64 bytes + CX_SHA3 = 7, ///< SHA3 Digest + DEPRECATED_0 = 8, ///< Keep compatibility + CX_BLAKE2B = 9, ///< Blake digest + // any bytes + CX_SHAKE128 = 10, ///< SHAKE-128 digest + // any bytes + CX_SHAKE256 = 11, ///< SHAKE-256 digest + CX_SHA3_256 = 12, ///< SHA3-256 digest + CX_SHA3_512 = 13, ///< SHA3-512 digest }; /** Convenience type. See #cx_md_e. */ typedef enum cx_md_e cx_md_t; @@ -90,23 +90,27 @@ typedef struct cx_hash_header_s cx_hash_t; * @brief Hash description. */ typedef struct { - cx_md_t md_type; ///< Message digest algorithm identifier - size_t output_size; ///< Output size - size_t block_size; ///< Block size - size_t ctx_size; ///< Related size of the context hash - cx_err_t (*init_func)(cx_hash_t *ctx); ///< Pointer to the initialization function - cx_err_t (*update_func)(cx_hash_t *ctx, const uint8_t *data, size_t len); ///< Pointer to the update function - cx_err_t (*finish_func)(cx_hash_t *ctx, uint8_t *digest); ///< Pointer to the final function - cx_err_t (*init_ex_func)(cx_hash_t *ctx, size_t output_size); ///< Pointer to the initialization function for extendable output - size_t (*output_size_func)(const cx_hash_t *ctx); ///< Pointer to the output size function + cx_md_t md_type; ///< Message digest algorithm identifier + size_t output_size; ///< Output size + size_t block_size; ///< Block size + size_t ctx_size; ///< Related size of the context hash + cx_err_t (*init_func)(cx_hash_t *ctx); ///< Pointer to the initialization function + cx_err_t (*update_func)(cx_hash_t *ctx, + const uint8_t *data, + size_t len); ///< Pointer to the update function + cx_err_t (*finish_func)(cx_hash_t *ctx, uint8_t *digest); ///< Pointer to the final function + cx_err_t (*init_ex_func)( + cx_hash_t *ctx, + size_t output_size); ///< Pointer to the initialization function for extendable output + size_t (*output_size_func)(const cx_hash_t *ctx); ///< Pointer to the output size function } cx_hash_info_t; /** * @brief Common message digest context, used as abstract type. */ struct cx_hash_header_s { - const cx_hash_info_t *info; ///< Hash description - uint32_t counter; ///< Number of already processed blocks + const cx_hash_info_t *info; ///< Hash description + uint32_t counter; ///< Number of already processed blocks }; size_t cx_hash_get_size(const cx_hash_t *ctx); @@ -139,16 +143,26 @@ size_t cx_hash_get_size(const cx_hash_t *ctx); * - INVALID_PARAMETER * - CX_INVALID_PARAMETER */ -cx_err_t cx_hash_no_throw(cx_hash_t *hash, uint32_t mode, const uint8_t *in, size_t len, uint8_t *out, size_t out_len); +cx_err_t cx_hash_no_throw(cx_hash_t *hash, + uint32_t mode, + const uint8_t *in, + size_t len, + uint8_t *out, + size_t out_len); /** * @deprecated * See #cx_hash_no_throw */ -DEPRECATED static inline size_t cx_hash ( cx_hash_t * hash, uint32_t mode, const unsigned char * in, unsigned int len, unsigned char * out, unsigned int out_len ) +DEPRECATED static inline size_t cx_hash(cx_hash_t *hash, + uint32_t mode, + const unsigned char *in, + unsigned int len, + unsigned char *out, + unsigned int out_len) { - CX_THROW(cx_hash_no_throw(hash, mode, in, len, out, out_len)); - return cx_hash_get_size(hash); + CX_THROW(cx_hash_no_throw(hash, mode, in, len, out, out_len)); + return cx_hash_get_size(hash); } /** @@ -223,4 +237,4 @@ cx_err_t cx_hash_final(cx_hash_t *hash, uint8_t *digest); #endif -#endif // HAVE_HASH +#endif // HAVE_HASH diff --git a/lib_cxng/include/lcx_hmac.h b/lib_cxng/include/lcx_hmac.h index 9d246a9f3..80010b2b5 100644 --- a/lib_cxng/include/lcx_hmac.h +++ b/lib_cxng/include/lcx_hmac.h @@ -1,20 +1,20 @@ /******************************************************************************* -* Ledger Nano S - Secure firmware -* (c) 2022 Ledger -* -* Licensed under the Apache License, Version 2.0 (the "License"); -* you may not use this file except in compliance with the License. -* You may obtain a copy of the License at -* -* http://www.apache.org/licenses/LICENSE-2.0 -* -* Unless required by applicable law or agreed to in writing, software -* distributed under the License is distributed on an "AS IS" BASIS, -* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -* See the License for the specific language governing permissions and -* limitations under the License. -********************************************************************************/ + * Ledger Nano S - Secure firmware + * (c) 2022 Ledger + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + ********************************************************************************/ /** * @file lcx_hmac.h @@ -41,22 +41,20 @@ * @brief HMAC context, abstract type */ typedef struct { - uint8_t key[128]; ///< Key - cx_hash_t hash_ctx; ///< Hash context + uint8_t key[128]; ///< Key + cx_hash_t hash_ctx; ///< Hash context } cx_hmac_t; - #ifdef HAVE_RIPEMD160 /** * @brief HMAC context, concrete type for RIPEMD160 */ typedef struct { - uint8_t key[128]; ///< Key - cx_ripemd160_t hash_ctx; ///< Hash context + uint8_t key[128]; ///< Key + cx_ripemd160_t hash_ctx; ///< Hash context } cx_hmac_ripemd160_t; - /** * @brief Initializes a HMAC-RIPEMD160 context. * @@ -75,27 +73,30 @@ typedef struct { * - CX_OK on success * - CX_INVALID_PARAMETER */ -cx_err_t cx_hmac_ripemd160_init_no_throw(cx_hmac_ripemd160_t *hmac, const uint8_t *key, size_t key_len); +cx_err_t cx_hmac_ripemd160_init_no_throw(cx_hmac_ripemd160_t *hmac, + const uint8_t *key, + size_t key_len); /** * @deprecated * See #cx_hmac_ripemd160_init_no_throw */ -DEPRECATED static inline int cx_hmac_ripemd160_init ( cx_hmac_ripemd160_t * hmac, const unsigned char * key, unsigned int key_len ) +DEPRECATED static inline int cx_hmac_ripemd160_init(cx_hmac_ripemd160_t *hmac, + const unsigned char *key, + unsigned int key_len) { - CX_THROW(cx_hmac_ripemd160_init_no_throw(hmac, key, key_len)); - return CX_RIPEMD160; + CX_THROW(cx_hmac_ripemd160_init_no_throw(hmac, key, key_len)); + return CX_RIPEMD160; } #endif - #if defined(HAVE_SHA224) || defined(HAVE_SHA256) /** * @brief HMAC context, concrete type for SHA-224/SHA-256 */ typedef struct { - uint8_t key[128]; ///< Key - cx_sha256_t hash_ctx; ///< Hash context + uint8_t key[128]; ///< Key + cx_sha256_t hash_ctx; ///< Hash context } cx_hmac_sha256_t; #endif @@ -148,10 +149,12 @@ cx_err_t cx_hmac_sha256_init_no_throw(cx_hmac_sha256_t *hmac, const uint8_t *key * @deprecated * See #cx_hmac_sha256_init_no_throw */ -DEPRECATED static inline int cx_hmac_sha256_init ( cx_hmac_sha256_t * hmac, const unsigned char * key, unsigned int key_len ) +DEPRECATED static inline int cx_hmac_sha256_init(cx_hmac_sha256_t *hmac, + const unsigned char *key, + unsigned int key_len) { - CX_THROW(cx_hmac_sha256_init_no_throw(hmac, key, key_len)); - return CX_SHA256; + CX_THROW(cx_hmac_sha256_init_no_throw(hmac, key, key_len)); + return CX_SHA256; } /** @@ -173,18 +176,22 @@ DEPRECATED static inline int cx_hmac_sha256_init ( cx_hmac_sha256_t * hmac, cons * * @return Length of the HMAC value. */ -size_t cx_hmac_sha256(const uint8_t *key, size_t key_len, const uint8_t *in, size_t len, uint8_t *mac, size_t mac_len); +size_t cx_hmac_sha256(const uint8_t *key, + size_t key_len, + const uint8_t *in, + size_t len, + uint8_t *mac, + size_t mac_len); #endif - #if defined(HAVE_SHA384) || defined(HAVE_SHA512) /** * @brief HMAC context, concrete type for SHA-384/SHA-512 */ typedef struct { - uint8_t key[128]; ///< Key - cx_sha512_t hash_ctx; ///< Hash context + uint8_t key[128]; ///< Key + cx_sha512_t hash_ctx; ///< Hash context } cx_hmac_sha512_t; #endif @@ -237,10 +244,12 @@ cx_err_t cx_hmac_sha512_init_no_throw(cx_hmac_sha512_t *hmac, const uint8_t *key * @deprecated * See #cx_hmac_sha512_init_no_throw */ -DEPRECATED static inline int cx_hmac_sha512_init ( cx_hmac_sha512_t * hmac, const unsigned char * key, unsigned int key_len ) +DEPRECATED static inline int cx_hmac_sha512_init(cx_hmac_sha512_t *hmac, + const unsigned char *key, + unsigned int key_len) { - CX_THROW(cx_hmac_sha512_init_no_throw(hmac, key, key_len)); - return CX_SHA512; + CX_THROW(cx_hmac_sha512_init_no_throw(hmac, key, key_len)); + return CX_SHA512; } /** @@ -262,7 +271,12 @@ DEPRECATED static inline int cx_hmac_sha512_init ( cx_hmac_sha512_t * hmac, cons * * @return Length of the HMAC value. */ -size_t cx_hmac_sha512(const uint8_t *key, size_t key_len, const uint8_t *in, size_t len, uint8_t *mac, size_t mac_len); +size_t cx_hmac_sha512(const uint8_t *key, + size_t key_len, + const uint8_t *in, + size_t len, + uint8_t *mac, + size_t mac_len); #endif @@ -297,36 +311,51 @@ size_t cx_hmac_sha512(const uint8_t *key, size_t key_len, const uint8_t *in, siz * - CX_OK on success * - CX_INVALID_PARAMETER */ -cx_err_t cx_hmac_no_throw(cx_hmac_t *hmac, uint32_t mode, const uint8_t *in, size_t len, uint8_t *mac, size_t mac_len); +cx_err_t cx_hmac_no_throw(cx_hmac_t *hmac, + uint32_t mode, + const uint8_t *in, + size_t len, + uint8_t *mac, + size_t mac_len); /** * @deprecated * See #cx_hmac_no_throw */ -DEPRECATED static inline int cx_hmac ( cx_hmac_t * hmac, uint32_t mode, const unsigned char * in, unsigned int len, unsigned char * mac, unsigned int mac_len ) +DEPRECATED static inline int cx_hmac(cx_hmac_t *hmac, + uint32_t mode, + const unsigned char *in, + unsigned int len, + unsigned char *mac, + unsigned int mac_len) { - CX_THROW(cx_hmac_no_throw(hmac, mode, in, len, mac, mac_len)); + CX_THROW(cx_hmac_no_throw(hmac, mode, in, len, mac, mac_len)); - switch (hmac->hash_ctx.info->md_type) { + switch (hmac->hash_ctx.info->md_type) { #ifdef HAVE_SHA224 - case CX_SHA224: return CX_SHA224_SIZE; + case CX_SHA224: + return CX_SHA224_SIZE; #endif #ifdef HAVE_SHA256 - case CX_SHA256: return CX_SHA256_SIZE; + case CX_SHA256: + return CX_SHA256_SIZE; #endif #ifdef HAVE_SHA384 - case CX_SHA384: return CX_SHA384_SIZE; + case CX_SHA384: + return CX_SHA384_SIZE; #endif #ifdef HAVE_SHA512 - case CX_SHA512: return CX_SHA512_SIZE; + case CX_SHA512: + return CX_SHA512_SIZE; #endif #ifdef HAVE_RIPEMD160 - case CX_RIPEMD160: return CX_RIPEMD160_SIZE; + case CX_RIPEMD160: + return CX_RIPEMD160_SIZE; #endif - default: - CX_THROW(CX_INVALID_PARAMETER); - return 0; - } + default: + CX_THROW(CX_INVALID_PARAMETER); + return 0; + } } /** @@ -385,8 +414,8 @@ cx_err_t cx_hmac_update(cx_hmac_t *hmac, const uint8_t *in, size_t in_len); * @return Error code: * - CX_OK on success */ -cx_err_t cx_hmac_final(cx_hmac_t *ctx, uint8_t *out, size_t *out_len) ; +cx_err_t cx_hmac_final(cx_hmac_t *ctx, uint8_t *out, size_t *out_len); #endif -#endif // HAVE_HMAC +#endif // HAVE_HMAC diff --git a/lib_cxng/include/lcx_math.h b/lib_cxng/include/lcx_math.h index 73e8f67f0..1cff13894 100644 --- a/lib_cxng/include/lcx_math.h +++ b/lib_cxng/include/lcx_math.h @@ -1,20 +1,20 @@ /******************************************************************************* -* Ledger Nano S - Secure firmware -* (c) 2022 Ledger -* -* Licensed under the Apache License, Version 2.0 (the "License"); -* you may not use this file except in compliance with the License. -* You may obtain a copy of the License at -* -* http://www.apache.org/licenses/LICENSE-2.0 -* -* Unless required by applicable law or agreed to in writing, software -* distributed under the License is distributed on an "AS IS" BASIS, -* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -* See the License for the specific language governing permissions and -* limitations under the License. -********************************************************************************/ + * Ledger Nano S - Secure firmware + * (c) 2022 Ledger + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + ********************************************************************************/ /** * @file lcx_math.h @@ -57,10 +57,11 @@ cx_err_t cx_math_cmp_no_throw(const uint8_t *a, const uint8_t *b, size_t length, * @deprecated * See #cx_math_cmp_no_throw */ -DEPRECATED static inline int32_t cx_math_cmp(const uint8_t *a, const uint8_t *b, size_t length) { - int diff; - CX_THROW(cx_math_cmp_no_throw(a, b, length, &diff)); - return diff; +DEPRECATED static inline int32_t cx_math_cmp(const uint8_t *a, const uint8_t *b, size_t length) +{ + int diff; + CX_THROW(cx_math_cmp_no_throw(a, b, length, &diff)); + return diff; } /** @@ -109,12 +110,13 @@ cx_err_t cx_math_add_no_throw(uint8_t *r, const uint8_t *a, const uint8_t *b, si * @throws CX_MEMORY_FULL * @throws CX_INVALID_PARAMETER */ -static inline uint32_t cx_math_add(uint8_t *r, const uint8_t *a, const uint8_t *b, size_t len) { - cx_err_t error = cx_math_add_no_throw(r, a, b, len); - if (error && error != CX_CARRY) { - THROW(error); - } - return (error == CX_CARRY); +static inline uint32_t cx_math_add(uint8_t *r, const uint8_t *a, const uint8_t *b, size_t len) +{ + cx_err_t error = cx_math_add_no_throw(r, a, b, len); + if (error && error != CX_CARRY) { + THROW(error); + } + return (error == CX_CARRY); } /** @@ -163,12 +165,13 @@ cx_err_t cx_math_sub_no_throw(uint8_t *r, const uint8_t *a, const uint8_t *b, si * @throws CX_MEMORY_FULL * @throws CX_INVALID_PARAMETER */ -static inline uint32_t cx_math_sub(uint8_t *r, const uint8_t *a, const uint8_t *b, size_t len) { - cx_err_t error = cx_math_sub_no_throw(r, a, b, len); - if (error && error != CX_CARRY) { - THROW(error); - } - return (error == CX_CARRY); +static inline uint32_t cx_math_sub(uint8_t *r, const uint8_t *a, const uint8_t *b, size_t len) +{ + cx_err_t error = cx_math_sub_no_throw(r, a, b, len); + if (error && error != CX_CARRY) { + THROW(error); + } + return (error == CX_CARRY); } /** @@ -196,8 +199,12 @@ cx_err_t cx_math_mult_no_throw(uint8_t *r, const uint8_t *a, const uint8_t *b, s * @deprecated * See #cx_math_mult_no_throw */ -DEPRECATED static inline void cx_math_mult(uint8_t *r, const uint8_t *a, const uint8_t *b, size_t len) { - CX_THROW(cx_math_mult_no_throw(r, a, b, len)); +DEPRECATED static inline void cx_math_mult(uint8_t *r, + const uint8_t *a, + const uint8_t *b, + size_t len) +{ + CX_THROW(cx_math_mult_no_throw(r, a, b, len)); } /** @@ -224,14 +231,23 @@ DEPRECATED static inline void cx_math_mult(uint8_t *r, const uint8_t *a, const u * - CX_MEMORY_FULL * - CX_INVALID_PARAMETER */ -cx_err_t cx_math_addm_no_throw(uint8_t *r, const uint8_t *a, const uint8_t *b, const uint8_t *m, size_t len); +cx_err_t cx_math_addm_no_throw(uint8_t *r, + const uint8_t *a, + const uint8_t *b, + const uint8_t *m, + size_t len); /** * @deprecated * See #cx_math_addm_no_throw */ -DEPRECATED static inline void cx_math_addm(uint8_t *r, const uint8_t *a, const uint8_t *b, const uint8_t *m, size_t len) { - CX_THROW(cx_math_addm_no_throw(r, a, b, m, len)); +DEPRECATED static inline void cx_math_addm(uint8_t *r, + const uint8_t *a, + const uint8_t *b, + const uint8_t *m, + size_t len) +{ + CX_THROW(cx_math_addm_no_throw(r, a, b, m, len)); } /** @@ -258,14 +274,23 @@ DEPRECATED static inline void cx_math_addm(uint8_t *r, const uint8_t *a, const u * - CX_MEMORY_FULL * - CX_INVALID_PARAMETER */ -cx_err_t cx_math_subm_no_throw(uint8_t *r, const uint8_t *a, const uint8_t *b, const uint8_t *m, size_t len); +cx_err_t cx_math_subm_no_throw(uint8_t *r, + const uint8_t *a, + const uint8_t *b, + const uint8_t *m, + size_t len); /** * @deprecated * See #cx_math_subm_no_throw */ -DEPRECATED static inline void cx_math_subm(uint8_t *r, const uint8_t *a, const uint8_t *b, const uint8_t *m, size_t len) { - CX_THROW(cx_math_subm_no_throw(r, a, b, m, len)); +DEPRECATED static inline void cx_math_subm(uint8_t *r, + const uint8_t *a, + const uint8_t *b, + const uint8_t *m, + size_t len) +{ + CX_THROW(cx_math_subm_no_throw(r, a, b, m, len)); } /** @@ -292,14 +317,23 @@ DEPRECATED static inline void cx_math_subm(uint8_t *r, const uint8_t *a, const u * - CX_INVALID_PARAMETER * - CX_INVALID_PARAMETER_VALUE */ -cx_err_t cx_math_multm_no_throw(uint8_t *r, const uint8_t *a, const uint8_t *b, const uint8_t *m, size_t len); +cx_err_t cx_math_multm_no_throw(uint8_t *r, + const uint8_t *a, + const uint8_t *b, + const uint8_t *m, + size_t len); /** * @deprecated * See #cx_math_multm_no_throw */ -DEPRECATED static inline void cx_math_multm(uint8_t *r, const uint8_t *a, const uint8_t *b, const uint8_t *m, size_t len) { - CX_THROW(cx_math_multm_no_throw(r, a, b, m, len)); +DEPRECATED static inline void cx_math_multm(uint8_t *r, + const uint8_t *a, + const uint8_t *b, + const uint8_t *m, + size_t len) +{ + CX_THROW(cx_math_multm_no_throw(r, a, b, m, len)); } /** @@ -329,8 +363,9 @@ cx_err_t cx_math_modm_no_throw(uint8_t *v, size_t len_v, const uint8_t *m, size_ * @deprecated * See #cx_math_modm_no_throw */ -DEPRECATED static inline void cx_math_modm(uint8_t *v, size_t len_v, const uint8_t *m, size_t len_m) { - CX_THROW(cx_math_modm_no_throw(v, len_v, m, len_m)); +DEPRECATED static inline void cx_math_modm(uint8_t *v, size_t len_v, const uint8_t *m, size_t len_m) +{ + CX_THROW(cx_math_modm_no_throw(v, len_v, m, len_m)); } /** @@ -358,14 +393,25 @@ DEPRECATED static inline void cx_math_modm(uint8_t *v, size_t len_v, const uint8 * - CX_MEMORY_FULL * - CX_INVALID_PARAMETER */ -cx_err_t cx_math_powm_no_throw(uint8_t *r, const uint8_t *a, const uint8_t *e, size_t len_e, const uint8_t *m, size_t len); +cx_err_t cx_math_powm_no_throw(uint8_t *r, + const uint8_t *a, + const uint8_t *e, + size_t len_e, + const uint8_t *m, + size_t len); /** * @deprecated * See #cx_math_powm_no_throw */ -DEPRECATED static inline void cx_math_powm(uint8_t *r, const uint8_t *a, const uint8_t *e, size_t len_e, const uint8_t *m, size_t len) { - CX_THROW(cx_math_powm_no_throw(r, a, e, len_e, m, len)); +DEPRECATED static inline void cx_math_powm(uint8_t *r, + const uint8_t *a, + const uint8_t *e, + size_t len_e, + const uint8_t *m, + size_t len) +{ + CX_THROW(cx_math_powm_no_throw(r, a, e, len_e, m, len)); } /** @@ -395,8 +441,12 @@ cx_err_t cx_math_invprimem_no_throw(uint8_t *r, const uint8_t *a, const uint8_t * @deprecated * See #cx_math_invprimem_no_throw */ -DEPRECATED static inline void cx_math_invprimem(uint8_t *r, const uint8_t *a, const uint8_t *m, size_t len) { - CX_THROW(cx_math_invprimem_no_throw(r, a, m, len)); +DEPRECATED static inline void cx_math_invprimem(uint8_t *r, + const uint8_t *a, + const uint8_t *m, + size_t len) +{ + CX_THROW(cx_math_invprimem_no_throw(r, a, m, len)); } /** @@ -427,8 +477,9 @@ cx_err_t cx_math_invintm_no_throw(uint8_t *r, uint32_t a, const uint8_t *m, size * @deprecated * See #cx_math_invintm_no_throw */ -DEPRECATED static inline void cx_math_invintm(uint8_t *r, uint32_t a, const uint8_t *m, size_t len) { - CX_THROW(cx_math_invintm_no_throw(r, a, m, len)); +DEPRECATED static inline void cx_math_invintm(uint8_t *r, uint32_t a, const uint8_t *m, size_t len) +{ + CX_THROW(cx_math_invintm_no_throw(r, a, m, len)); } /** @@ -456,10 +507,11 @@ cx_err_t cx_math_is_prime_no_throw(const uint8_t *r, size_t len, bool *prime); * @deprecated * See #cx_math_is_prime_no_throw */ -DEPRECATED static inline bool cx_math_is_prime(const uint8_t *r, size_t len) { - bool prime; - CX_THROW(cx_math_is_prime_no_throw(r, len, &prime)); - return prime; +DEPRECATED static inline bool cx_math_is_prime(const uint8_t *r, size_t len) +{ + bool prime; + CX_THROW(cx_math_is_prime_no_throw(r, len, &prime)); + return prime; } /** @@ -485,8 +537,9 @@ cx_err_t cx_math_next_prime_no_throw(uint8_t *r, uint32_t len); * @deprecated * See #cx_math_next_prime_no_throw */ -DEPRECATED static inline void cx_math_next_prime(uint8_t *r, uint32_t len) { - CX_THROW(cx_math_next_prime_no_throw(r, len)); +DEPRECATED static inline void cx_math_next_prime(uint8_t *r, uint32_t len) +{ + CX_THROW(cx_math_next_prime_no_throw(r, len)); } /** @@ -498,16 +551,17 @@ DEPRECATED static inline void cx_math_next_prime(uint8_t *r, uint32_t len) { * * @return 1 if a is all zero, 0 otherwise. */ -static inline bool cx_math_is_zero(const uint8_t *a, size_t len) { - uint32_t i; - for (i=0; i - * RIPEMD-160 for more details. + * RIPEMD-160 is a 160-bit cryptographic hash function. Refer to RIPEMD-160 for more details. */ #ifdef HAVE_RIPEMD160 @@ -39,13 +39,13 @@ * @brief RIPEMD-160 context. */ struct cx_ripemd160_s { - struct cx_hash_header_s header; ///< See #cx_hash_header_s - size_t blen; ///< Pending partial block length - uint8_t block[64]; ///< Pending partial block - // After finishing the digest, - // contains the digest if correct - // parameters are passed. - uint8_t acc[5 * 4]; ///< Current digest state + struct cx_hash_header_s header; ///< See #cx_hash_header_s + size_t blen; ///< Pending partial block length + uint8_t block[64]; ///< Pending partial block + // After finishing the digest, + // contains the digest if correct + // parameters are passed. + uint8_t acc[5 * 4]; ///< Current digest state }; /** Convenience type. See #cx_ripemd160_s. */ typedef struct cx_ripemd160_s cx_ripemd160_t; @@ -69,10 +69,10 @@ cx_err_t cx_ripemd160_init_no_throw(cx_ripemd160_t *hash); * * @return RIPEMD160 identifier. */ -static inline int cx_ripemd160_init ( cx_ripemd160_t * hash ) +static inline int cx_ripemd160_init(cx_ripemd160_t *hash) { - cx_ripemd160_init_no_throw(hash); - return CX_RIPEMD160; + cx_ripemd160_init_no_throw(hash); + return CX_RIPEMD160; } /** @@ -92,4 +92,4 @@ size_t cx_hash_ripemd160(const uint8_t *in, size_t in_len, uint8_t *out, size_t #endif -#endif // HAVE_RIPEMD160 +#endif // HAVE_RIPEMD160 diff --git a/lib_cxng/include/lcx_rng.h b/lib_cxng/include/lcx_rng.h index 022c0dbe1..087273862 100644 --- a/lib_cxng/include/lcx_rng.h +++ b/lib_cxng/include/lcx_rng.h @@ -1,28 +1,28 @@ /******************************************************************************* -* Ledger Nano S - Secure firmware -* (c) 2022 Ledger -* -* Licensed under the Apache License, Version 2.0 (the "License"); -* you may not use this file except in compliance with the License. -* You may obtain a copy of the License at -* -* http://www.apache.org/licenses/LICENSE-2.0 -* -* Unless required by applicable law or agreed to in writing, software -* distributed under the License is distributed on an "AS IS" BASIS, -* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -* See the License for the specific language governing permissions and -* limitations under the License. -********************************************************************************/ + * Ledger Nano S - Secure firmware + * (c) 2022 Ledger + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + ********************************************************************************/ /** * @file lcx_rng.h * @brief Random Number Generation * - * Random numbers with different sizes can be generated: a 8-bit random number, a 32-bit random number - * or a random number of arbitrary size. In this case, the number is returned as a buffer of random bytes. - * The random number can also be generated within a specific range. + * Random numbers with different sizes can be generated: a 8-bit random number, a 32-bit random + * number or a random number of arbitrary size. In this case, the number is returned as a buffer of + * random bytes. The random number can also be generated within a specific range. */ #ifdef HAVE_RNG @@ -57,8 +57,8 @@ void cx_rng_no_throw(uint8_t *buffer, size_t len); */ static inline unsigned char *cx_rng(uint8_t *buffer, size_t len) { - cx_rng_no_throw(buffer, len); - return buffer; + cx_rng_no_throw(buffer, len); + return buffer; } /** @@ -66,10 +66,11 @@ static inline unsigned char *cx_rng(uint8_t *buffer, size_t len) * * @return A 32-bit random number. */ -static inline uint32_t cx_rng_u32(void) { - uint32_t r; - cx_rng_no_throw((uint8_t *)&r, sizeof(uint32_t)); - return r; +static inline uint32_t cx_rng_u32(void) +{ + uint32_t r; + cx_rng_no_throw((uint8_t *) &r, sizeof(uint32_t)); + return r; } /** @@ -77,10 +78,11 @@ static inline uint32_t cx_rng_u32(void) { * * @return A 8-bit random number. */ -static inline uint8_t cx_rng_u8(void) { - uint8_t r; - cx_rng_no_throw((uint8_t *)&r, sizeof(uint8_t)); - return r; +static inline uint8_t cx_rng_u8(void) +{ + uint8_t r; + cx_rng_no_throw((uint8_t *) &r, sizeof(uint8_t)); + return r; } typedef uint32_t (*cx_rng_u32_range_randfunc_t)(void); @@ -114,8 +116,9 @@ uint32_t cx_rng_u32_range_func(uint32_t a, uint32_t b, cx_rng_u32_range_randfunc * * @return A 32-bit random number. */ -static inline uint32_t cx_rng_u32_range(uint32_t a, uint32_t b) { - return cx_rng_u32_range_func(a, b, cx_rng_u32); +static inline uint32_t cx_rng_u32_range(uint32_t a, uint32_t b) +{ + return cx_rng_u32_range_func(a, b, cx_rng_u32); } /** @@ -144,12 +147,16 @@ static inline uint32_t cx_rng_u32_range(uint32_t a, uint32_t b) { * - CX_OK on success * - CX_INVALID_PARAMETER */ -cx_err_t cx_rng_rfc6979(cx_md_t hash_id, - const uint8_t *x, size_t x_len, - const uint8_t *h1, size_t h1_len, - const uint8_t *q, size_t q_len, - uint8_t *out, size_t out_len) ; +cx_err_t cx_rng_rfc6979(cx_md_t hash_id, + const uint8_t *x, + size_t x_len, + const uint8_t *h1, + size_t h1_len, + const uint8_t *q, + size_t q_len, + uint8_t *out, + size_t out_len); -#endif // LCX_RNG_H +#endif // LCX_RNG_H -#endif // HAVE_RNG +#endif // HAVE_RNG diff --git a/lib_cxng/include/lcx_rsa.h b/lib_cxng/include/lcx_rsa.h index 7b0e9b8db..01348ab19 100644 --- a/lib_cxng/include/lcx_rsa.h +++ b/lib_cxng/include/lcx_rsa.h @@ -1,20 +1,20 @@ /******************************************************************************* -* Ledger Nano S - Secure firmware -* (c) 2022 Ledger -* -* Licensed under the Apache License, Version 2.0 (the "License"); -* you may not use this file except in compliance with the License. -* You may obtain a copy of the License at -* -* http://www.apache.org/licenses/LICENSE-2.0 -* -* Unless required by applicable law or agreed to in writing, software -* distributed under the License is distributed on an "AS IS" BASIS, -* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -* See the License for the specific language governing permissions and -* limitations under the License. -********************************************************************************/ + * Ledger Nano S - Secure firmware + * (c) 2022 Ledger + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + ********************************************************************************/ /** * @file lcx_rsa.h @@ -43,18 +43,18 @@ * for RSA operations. */ struct cx_rsa_public_key_s { - size_t size; ///< Key size in bytes - uint8_t e[4]; ///< 32-bit public exponent - uint8_t n[1]; ///< Public modulus + size_t size; ///< Key size in bytes + uint8_t e[4]; ///< 32-bit public exponent + uint8_t n[1]; ///< Public modulus }; /** * @brief Abstract RSA private key. */ struct cx_rsa_private_key_s { - size_t size; ///< Key size in bytes - uint8_t d[1]; ///< Private exponent - uint8_t n[1]; ///< Public modulus + size_t size; ///< Key size in bytes + uint8_t d[1]; ///< Private exponent + uint8_t n[1]; ///< Public modulus }; /** Convenience type. See #cx_rsa_public_key_s. */ typedef struct cx_rsa_public_key_s cx_rsa_public_key_t; @@ -63,15 +63,15 @@ typedef struct cx_rsa_private_key_s cx_rsa_private_key_t; /** 1024-bit RSA public key */ struct cx_rsa_1024_public_key_s { - size_t size; ///< @copydoc cx_rsa_public_key_s::size - uint8_t e[4]; ///< @copydoc cx_rsa_public_key_s::e - uint8_t n[128]; ///< @copydoc cx_rsa_public_key_s::n + size_t size; ///< @copydoc cx_rsa_public_key_s::size + uint8_t e[4]; ///< @copydoc cx_rsa_public_key_s::e + uint8_t n[128]; ///< @copydoc cx_rsa_public_key_s::n }; /** 1024-bit RSA private key */ struct cx_rsa_1024_private_key_s { - size_t size; ///< @copydoc cx_rsa_private_key_s::size - uint8_t d[128]; ///< @copydoc cx_rsa_private_key_s::d - uint8_t n[128]; ///< @copydoc cx_rsa_private_key_s::n + size_t size; ///< @copydoc cx_rsa_private_key_s::size + uint8_t d[128]; ///< @copydoc cx_rsa_private_key_s::d + uint8_t n[128]; ///< @copydoc cx_rsa_private_key_s::n }; /** Convenience type. See #cx_rsa_1024_public_key_s. */ typedef struct cx_rsa_1024_public_key_s cx_rsa_1024_public_key_t; @@ -80,15 +80,15 @@ typedef struct cx_rsa_1024_private_key_s cx_rsa_1024_private_key_t; /** 2048-bit RSA public key */ struct cx_rsa_2048_public_key_s { - size_t size; ///< @copydoc cx_rsa_public_key_s::size - uint8_t e[4]; ///< @copydoc cx_rsa_public_key_s::e - uint8_t n[256]; ///< @copydoc cx_rsa_public_key_s::n + size_t size; ///< @copydoc cx_rsa_public_key_s::size + uint8_t e[4]; ///< @copydoc cx_rsa_public_key_s::e + uint8_t n[256]; ///< @copydoc cx_rsa_public_key_s::n }; /** 2048-bit RSA private key */ struct cx_rsa_2048_private_key_s { - size_t size; ///< @copydoc cx_rsa_private_key_s::size - uint8_t d[256]; ///< @copydoc cx_rsa_private_key_s::d - uint8_t n[256]; ///< @copydoc cx_rsa_private_key_s::n + size_t size; ///< @copydoc cx_rsa_private_key_s::size + uint8_t d[256]; ///< @copydoc cx_rsa_private_key_s::d + uint8_t n[256]; ///< @copydoc cx_rsa_private_key_s::n }; /** Convenience type. See #cx_rsa_2048_public_key_s. */ typedef struct cx_rsa_2048_public_key_s cx_rsa_2048_public_key_t; @@ -97,15 +97,15 @@ typedef struct cx_rsa_2048_private_key_s cx_rsa_2048_private_key_t; /** 3072-bit RSA public key */ struct cx_rsa_3072_public_key_s { - size_t size; ///< @copydoc cx_rsa_public_key_s::size - uint8_t e[4]; ///< @copydoc cx_rsa_public_key_s::e - uint8_t n[384]; ///< @copydoc cx_rsa_public_key_s::n + size_t size; ///< @copydoc cx_rsa_public_key_s::size + uint8_t e[4]; ///< @copydoc cx_rsa_public_key_s::e + uint8_t n[384]; ///< @copydoc cx_rsa_public_key_s::n }; /** 3072-bit RSA private key */ struct cx_rsa_3072_private_key_s { - size_t size; ///< @copydoc cx_rsa_private_key_s::size - uint8_t d[384]; ///< @copydoc cx_rsa_private_key_s::d - uint8_t n[384]; ///< @copydoc cx_rsa_private_key_s::n + size_t size; ///< @copydoc cx_rsa_private_key_s::size + uint8_t d[384]; ///< @copydoc cx_rsa_private_key_s::d + uint8_t n[384]; ///< @copydoc cx_rsa_private_key_s::n }; /** Convenience type. See #cx_rsa_3072_public_key_s. */ typedef struct cx_rsa_3072_public_key_s cx_rsa_3072_public_key_t; @@ -114,15 +114,15 @@ typedef struct cx_rsa_3072_private_key_s cx_rsa_3072_private_key_t; /** 4096-bit RSA public key */ struct cx_rsa_4096_public_key_s { - size_t size; ///< @copydoc cx_rsa_public_key_s::size - uint8_t e[4]; ///< @copydoc cx_rsa_public_key_s::e - uint8_t n[512]; ///< @copydoc cx_rsa_public_key_s::n + size_t size; ///< @copydoc cx_rsa_public_key_s::size + uint8_t e[4]; ///< @copydoc cx_rsa_public_key_s::e + uint8_t n[512]; ///< @copydoc cx_rsa_public_key_s::n }; /** 4096-bit RSA private key */ struct cx_rsa_4096_private_key_s { - size_t size; ///< @copydoc cx_rsa_private_key_s::size - uint8_t d[512]; ///< @copydoc cx_rsa_private_key_s::d - uint8_t n[512]; ///< @copydoc cx_rsa_private_key_s::n + size_t size; ///< @copydoc cx_rsa_private_key_s::size + uint8_t d[512]; ///< @copydoc cx_rsa_private_key_s::d + uint8_t n[512]; ///< @copydoc cx_rsa_private_key_s::n }; /** Convenience type. See #cx_rsa_4096_public_key_s. */ typedef struct cx_rsa_4096_public_key_s cx_rsa_4096_public_key_t; @@ -152,20 +152,24 @@ typedef struct cx_rsa_4096_private_key_s cx_rsa_4096_private_key_t; * - CX_OK on success * - CX_INVALID_PARAMETER */ -cx_err_t cx_rsa_init_public_key_no_throw(const uint8_t * exponent, - size_t exponent_len, - const uint8_t * modulus, - size_t modulus_len, - cx_rsa_public_key_t *key); +cx_err_t cx_rsa_init_public_key_no_throw(const uint8_t *exponent, + size_t exponent_len, + const uint8_t *modulus, + size_t modulus_len, + cx_rsa_public_key_t *key); /** * @deprecated * See #cx_rsa_init_public_key_no_throw */ -DEPRECATED static inline int cx_rsa_init_public_key ( const unsigned char * exponent, unsigned int exponent_len, const unsigned char * modulus, unsigned int modulus_len, cx_rsa_public_key_t * key ) +DEPRECATED static inline int cx_rsa_init_public_key(const unsigned char *exponent, + unsigned int exponent_len, + const unsigned char *modulus, + unsigned int modulus_len, + cx_rsa_public_key_t *key) { - CX_THROW(cx_rsa_init_public_key_no_throw(exponent, exponent_len, modulus, modulus_len, key)); - return modulus_len; + CX_THROW(cx_rsa_init_public_key_no_throw(exponent, exponent_len, modulus, modulus_len, key)); + return modulus_len; } /** @@ -191,20 +195,24 @@ DEPRECATED static inline int cx_rsa_init_public_key ( const unsigned char * expo * - CX_OK on success * - CX_INVALID_PARAMETER */ -cx_err_t cx_rsa_init_private_key_no_throw(const uint8_t * exponent, - size_t exponent_len, - const uint8_t * modulus, - size_t modulus_len, - cx_rsa_private_key_t *key); +cx_err_t cx_rsa_init_private_key_no_throw(const uint8_t *exponent, + size_t exponent_len, + const uint8_t *modulus, + size_t modulus_len, + cx_rsa_private_key_t *key); /** * @deprecated * See #cx_rsa_init_private_key_no_throw */ -DEPRECATED static inline int cx_rsa_init_private_key ( const unsigned char * exponent, unsigned int exponent_len, const unsigned char * modulus, unsigned int modulus_len, cx_rsa_private_key_t * key ) +DEPRECATED static inline int cx_rsa_init_private_key(const unsigned char *exponent, + unsigned int exponent_len, + const unsigned char *modulus, + unsigned int modulus_len, + cx_rsa_private_key_t *key) { - CX_THROW(cx_rsa_init_private_key_no_throw(exponent, exponent_len, modulus, modulus_len, key)); - return modulus_len; + CX_THROW(cx_rsa_init_private_key_no_throw(exponent, exponent_len, modulus, modulus_len, key)); + return modulus_len; } /** @@ -227,10 +235,9 @@ DEPRECATED static inline int cx_rsa_init_private_key ( const unsigned char * exp * * @param[in] exponent_len Length of the exponent. * - * @param[in] externalPQ Pointer to the prime factors of the modulus or NULL pointer. Each prime consists of modulus_len/2 - * bytes in big endian order. - * P = externalPQ[0:modulus_len/2-1], Q = externalPQ[modulus_len/2 : modulus_len-1] - * There is no verification on provided P and Q. + * @param[in] externalPQ Pointer to the prime factors of the modulus or NULL pointer. Each prime + * consists of modulus_len/2 bytes in big endian order. P = externalPQ[0:modulus_len/2-1], Q = + * externalPQ[modulus_len/2 : modulus_len-1] There is no verification on provided P and Q. * * @return Error code: * - CX_OK on success @@ -242,21 +249,27 @@ DEPRECATED static inline int cx_rsa_init_private_key ( const unsigned char * exp * - CX_INTERNAL_ERROR * - CX_OVERFLOW */ -cx_err_t cx_rsa_generate_pair_no_throw(size_t modulus_len, - cx_rsa_public_key_t * public_key, - cx_rsa_private_key_t *private_key, - const uint8_t * pub_exponent, - size_t exponent_len, - const uint8_t * externalPQ); +cx_err_t cx_rsa_generate_pair_no_throw(size_t modulus_len, + cx_rsa_public_key_t *public_key, + cx_rsa_private_key_t *private_key, + const uint8_t *pub_exponent, + size_t exponent_len, + const uint8_t *externalPQ); /** * @deprecated * See #cx_rsa_generate_pair_no_throw */ -DEPRECATED static inline int cx_rsa_generate_pair ( unsigned int modulus_len, cx_rsa_public_key_t * public_key, cx_rsa_private_key_t * private_key, const unsigned char * pub_exponent, unsigned int exponent_len, const unsigned char * externalPQ ) +DEPRECATED static inline int cx_rsa_generate_pair(unsigned int modulus_len, + cx_rsa_public_key_t *public_key, + cx_rsa_private_key_t *private_key, + const unsigned char *pub_exponent, + unsigned int exponent_len, + const unsigned char *externalPQ) { - CX_THROW(cx_rsa_generate_pair_no_throw(modulus_len, public_key, private_key, pub_exponent, exponent_len, externalPQ)); - return modulus_len; + CX_THROW(cx_rsa_generate_pair_no_throw( + modulus_len, public_key, private_key, pub_exponent, exponent_len, externalPQ)); + return modulus_len; } /** @@ -301,9 +314,9 @@ DEPRECATED static inline int cx_rsa_generate_pair ( unsigned int modulus_len, cx cx_err_t cx_rsa_sign_with_salt_len(const cx_rsa_private_key_t *key, uint32_t mode, cx_md_t hashID, - const uint8_t * hash, + const uint8_t *hash, size_t hash_len, - uint8_t * sig, + uint8_t *sig, size_t sig_len, size_t salt_len); @@ -346,21 +359,27 @@ cx_err_t cx_rsa_sign_with_salt_len(const cx_rsa_private_key_t *key, * - CX_NOT_LOCKED */ cx_err_t cx_rsa_sign_no_throw(const cx_rsa_private_key_t *key, - uint32_t mode, - cx_md_t hashID, - const uint8_t * hash, - size_t hash_len, - uint8_t * sig, - size_t sig_len); + uint32_t mode, + cx_md_t hashID, + const uint8_t *hash, + size_t hash_len, + uint8_t *sig, + size_t sig_len); /** * @deprecated * See #cx_rsa_sign_no_throw */ -DEPRECATED static inline int cx_rsa_sign ( const cx_rsa_private_key_t * key, int mode, cx_md_t hashID, const unsigned char * hash, unsigned int hash_len, unsigned char * sig, unsigned int sig_len ) +DEPRECATED static inline int cx_rsa_sign(const cx_rsa_private_key_t *key, + int mode, + cx_md_t hashID, + const unsigned char *hash, + unsigned int hash_len, + unsigned char *sig, + unsigned int sig_len) { - CX_THROW(cx_rsa_sign_no_throw(key, mode, hashID, hash, hash_len, sig, sig_len)); - return key->size; + CX_THROW(cx_rsa_sign_no_throw(key, mode, hashID, hash, hash_len, sig, sig_len)); + return key->size; } /** @@ -399,9 +418,9 @@ DEPRECATED static inline int cx_rsa_sign ( const cx_rsa_private_key_t * key, int bool cx_rsa_verify_with_salt_len(const cx_rsa_public_key_t *key, uint32_t mode, cx_md_t hashID, - const uint8_t * hash, + const uint8_t *hash, size_t hash_len, - uint8_t * sig, + uint8_t *sig, size_t sig_len, size_t salt_len); @@ -440,13 +459,13 @@ bool cx_rsa_verify_with_salt_len(const cx_rsa_public_key_t *key, * @return 1 if the signature is verified, 0 otherwise. * */ - bool cx_rsa_verify(const cx_rsa_public_key_t *key, - uint32_t mode, - cx_md_t hashID, - const uint8_t * hash, - size_t hash_len, - uint8_t * sig, - size_t sig_len); +bool cx_rsa_verify(const cx_rsa_public_key_t *key, + uint32_t mode, + cx_md_t hashID, + const uint8_t *hash, + size_t hash_len, + uint8_t *sig, + size_t sig_len); /** * @brief Encrypts a message according to RSA specification. @@ -481,21 +500,27 @@ bool cx_rsa_verify_with_salt_len(const cx_rsa_public_key_t *key, * - CX_NOT_LOCKED */ cx_err_t cx_rsa_encrypt_no_throw(const cx_rsa_public_key_t *key, - uint32_t mode, - cx_md_t hashID, - const uint8_t * mesg, - size_t mesg_len, - uint8_t * enc, - size_t enc_len); + uint32_t mode, + cx_md_t hashID, + const uint8_t *mesg, + size_t mesg_len, + uint8_t *enc, + size_t enc_len); /** * @deprecated * See #cx_rsa_encrypt_no_throw */ -DEPRECATED static inline int cx_rsa_encrypt ( const cx_rsa_public_key_t * key, int mode, cx_md_t hashID, const unsigned char * mesg, unsigned int mesg_len, unsigned char * enc, unsigned int enc_len ) +DEPRECATED static inline int cx_rsa_encrypt(const cx_rsa_public_key_t *key, + int mode, + cx_md_t hashID, + const unsigned char *mesg, + unsigned int mesg_len, + unsigned char *enc, + unsigned int enc_len) { - CX_THROW(cx_rsa_encrypt_no_throw(key, mode, hashID, mesg, mesg_len, enc, enc_len)); - return key->size; + CX_THROW(cx_rsa_encrypt_no_throw(key, mode, hashID, mesg, mesg_len, enc, enc_len)); + return key->size; } /** @@ -531,24 +556,30 @@ DEPRECATED static inline int cx_rsa_encrypt ( const cx_rsa_public_key_t * key, i * - CX_NOT_LOCKED */ cx_err_t cx_rsa_decrypt_no_throw(const cx_rsa_private_key_t *key, - uint32_t mode, - cx_md_t hashID, - const uint8_t * mesg, - size_t mesg_len, - uint8_t * dec, - size_t * dec_len); + uint32_t mode, + cx_md_t hashID, + const uint8_t *mesg, + size_t mesg_len, + uint8_t *dec, + size_t *dec_len); /** * @deprecated * See #cx_rsa_decrypt_no_throw */ -DEPRECATED static inline int cx_rsa_decrypt ( const cx_rsa_private_key_t * key, int mode, cx_md_t hashID, const unsigned char * mesg, unsigned int mesg_len, unsigned char * dec, unsigned int dec_len ) +DEPRECATED static inline int cx_rsa_decrypt(const cx_rsa_private_key_t *key, + int mode, + cx_md_t hashID, + const unsigned char *mesg, + unsigned int mesg_len, + unsigned char *dec, + unsigned int dec_len) { - size_t dec_len_ = dec_len; - CX_THROW(cx_rsa_decrypt_no_throw(key, mode, hashID, mesg, mesg_len, dec, &dec_len_)); - return dec_len_; + size_t dec_len_ = dec_len; + CX_THROW(cx_rsa_decrypt_no_throw(key, mode, hashID, mesg, mesg_len, dec, &dec_len_)); + return dec_len_; } #endif -#endif // HAVE_RSA +#endif // HAVE_RSA diff --git a/lib_cxng/include/lcx_sha256.h b/lib_cxng/include/lcx_sha256.h index 80f32da99..d1472c5a5 100644 --- a/lib_cxng/include/lcx_sha256.h +++ b/lib_cxng/include/lcx_sha256.h @@ -1,20 +1,20 @@ /******************************************************************************* -* Ledger Nano S - Secure firmware -* (c) 2022 Ledger -* -* Licensed under the Apache License, Version 2.0 (the "License"); -* you may not use this file except in compliance with the License. -* You may obtain a copy of the License at -* -* http://www.apache.org/licenses/LICENSE-2.0 -* -* Unless required by applicable law or agreed to in writing, software -* distributed under the License is distributed on an "AS IS" BASIS, -* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -* See the License for the specific language governing permissions and -* limitations under the License. -********************************************************************************/ + * Ledger Nano S - Secure firmware + * (c) 2022 Ledger + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + ********************************************************************************/ /** * @file lcx_sha256.h @@ -49,10 +49,10 @@ * @brief SHA-224 and SHA-256 context */ struct cx_sha256_s { - struct cx_hash_header_s header; ///< @copydoc cx_ripemd160_s::header - size_t blen; ///< @copydoc cx_ripemd160_s::blen - uint8_t block[64]; ///< @copydoc cx_ripemd160_s::block - uint8_t acc[8 * 4]; ///< @copydoc cx_ripemd160_s::acc + struct cx_hash_header_s header; ///< @copydoc cx_ripemd160_s::header + size_t blen; ///< @copydoc cx_ripemd160_s::blen + uint8_t block[64]; ///< @copydoc cx_ripemd160_s::block + uint8_t acc[8 * 4]; ///< @copydoc cx_ripemd160_s::acc }; /** Convenience type. See #cx_sha256_s. */ typedef struct cx_sha256_s cx_sha256_t; @@ -77,10 +77,10 @@ cx_err_t cx_sha224_init_no_throw(cx_sha256_t *hash); * * @return SHA224 identifier. */ -static inline int cx_sha224_init ( cx_sha256_t * hash ) +static inline int cx_sha224_init(cx_sha256_t *hash) { - cx_sha224_init_no_throw(hash); - return CX_SHA224; + cx_sha224_init_no_throw(hash); + return CX_SHA224; } #endif @@ -103,10 +103,10 @@ cx_err_t cx_sha256_init_no_throw(cx_sha256_t *hash); * * @return SHA256 identifier. */ -static inline int cx_sha256_init ( cx_sha256_t * hash ) +static inline int cx_sha256_init(cx_sha256_t *hash) { - cx_sha256_init_no_throw(hash); - return CX_SHA256; + cx_sha256_init_no_throw(hash); + return CX_SHA256; } /** @@ -122,8 +122,8 @@ static inline int cx_sha256_init ( cx_sha256_t * hash ) * This is actually 256 bits. * */ - size_t cx_hash_sha256(const uint8_t *in, size_t len, uint8_t *out, size_t out_len); +size_t cx_hash_sha256(const uint8_t *in, size_t len, uint8_t *out, size_t out_len); #endif -#endif // defined(HAVE_SHA256) || defined(HAVE_SHA224) +#endif // defined(HAVE_SHA256) || defined(HAVE_SHA224) diff --git a/lib_cxng/include/lcx_sha3.h b/lib_cxng/include/lcx_sha3.h index d89ad49ac..50c1573d1 100644 --- a/lib_cxng/include/lcx_sha3.h +++ b/lib_cxng/include/lcx_sha3.h @@ -1,20 +1,20 @@ /******************************************************************************* -* Ledger Nano S - Secure firmware -* (c) 2022 Ledger -* -* Licensed under the Apache License, Version 2.0 (the "License"); -* you may not use this file except in compliance with the License. -* You may obtain a copy of the License at -* -* http://www.apache.org/licenses/LICENSE-2.0 -* -* Unless required by applicable law or agreed to in writing, software -* distributed under the License is distributed on an "AS IS" BASIS, -* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -* See the License for the specific language governing permissions and -* limitations under the License. -********************************************************************************/ + * Ledger Nano S - Secure firmware + * (c) 2022 Ledger + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + ********************************************************************************/ /** * @file lcx_sha3.h @@ -39,12 +39,12 @@ * @brief KECCAK, SHA3 and SHA3-XOF context */ struct cx_sha3_s { - struct cx_hash_header_s header; ///< @copydoc cx_ripemd160_s::header - size_t output_size; ///< Output digest size - size_t block_size; ///< Input block size - size_t blen; ///< @copydoc cx_ripemd160_s::blen - uint8_t block[200]; ///< @copydoc cx_ripemd160_s::block - uint64bits_t acc[25]; ///< @copydoc cx_ripemd160_s::acc + struct cx_hash_header_s header; ///< @copydoc cx_ripemd160_s::header + size_t output_size; ///< Output digest size + size_t block_size; ///< Input block size + size_t blen; ///< @copydoc cx_ripemd160_s::blen + uint8_t block[200]; ///< @copydoc cx_ripemd160_s::block + uint64bits_t acc[25]; ///< @copydoc cx_ripemd160_s::acc }; /** Convenience type. See #cx_sha3_s. */ typedef struct cx_sha3_s cx_sha3_t; @@ -73,10 +73,10 @@ cx_err_t cx_sha3_init_no_throw(cx_sha3_t *hash, size_t size); * @deprecated * See #cx_sha3_init_no_throw */ -DEPRECATED static inline int cx_sha3_init ( cx_sha3_t * hash, size_t size ) +DEPRECATED static inline int cx_sha3_init(cx_sha3_t *hash, size_t size) { - CX_THROW(cx_sha3_init_no_throw(hash, size)); - return CX_SHA3; + CX_THROW(cx_sha3_init_no_throw(hash, size)); + return CX_SHA3; } /** @@ -104,10 +104,10 @@ cx_err_t cx_keccak_init_no_throw(cx_sha3_t *hash, size_t size); * @deprecated * See #cx_keccak_init_no_throw */ -DEPRECATED static inline int cx_keccak_init ( cx_sha3_t * hash, size_t size ) +DEPRECATED static inline int cx_keccak_init(cx_sha3_t *hash, size_t size) { - CX_THROW(cx_keccak_init_no_throw(hash, size)); - return CX_KECCAK; + CX_THROW(cx_keccak_init_no_throw(hash, size)); + return CX_KECCAK; } /** @@ -134,10 +134,10 @@ cx_err_t cx_shake128_init_no_throw(cx_sha3_t *hash, size_t out_size); * @deprecated * See #cx_shake128_init_no_throw */ -DEPRECATED static inline int cx_shake128_init ( cx_sha3_t * hash, unsigned int out_size ) +DEPRECATED static inline int cx_shake128_init(cx_sha3_t *hash, unsigned int out_size) { - CX_THROW(cx_shake128_init_no_throw(hash, out_size)); - return CX_SHAKE128; + CX_THROW(cx_shake128_init_no_throw(hash, out_size)); + return CX_SHAKE128; } /** @@ -164,10 +164,10 @@ cx_err_t cx_shake256_init_no_throw(cx_sha3_t *hash, size_t out_size); * @deprecated * See #cx_shake256_init_no_throw */ -DEPRECATED static inline int cx_shake256_init ( cx_sha3_t * hash, unsigned int out_size ) +DEPRECATED static inline int cx_shake256_init(cx_sha3_t *hash, unsigned int out_size) { - CX_THROW(cx_shake256_init_no_throw(hash, out_size)); - return CX_SHAKE256; + CX_THROW(cx_shake256_init_no_throw(hash, out_size)); + return CX_SHAKE256; } /** @@ -196,17 +196,20 @@ cx_err_t cx_sha3_xof_init_no_throw(cx_sha3_t *hash, size_t size, size_t out_leng * @deprecated * See #cx_sha3_xof_init_no_throw */ -DEPRECATED static inline int cx_sha3_xof_init ( cx_sha3_t * hash, unsigned int size, unsigned int out_length ) +DEPRECATED static inline int cx_sha3_xof_init(cx_sha3_t *hash, + unsigned int size, + unsigned int out_length) { - CX_THROW(cx_sha3_xof_init_no_throw(hash, size, out_length)); - - if (size == 128) { - return CX_SHAKE128; - } else { - return CX_SHAKE256; - } + CX_THROW(cx_sha3_xof_init_no_throw(hash, size, out_length)); + + if (size == 128) { + return CX_SHAKE128; + } + else { + return CX_SHAKE256; + } } #endif -#endif // HAVE_SHA3 +#endif // HAVE_SHA3 diff --git a/lib_cxng/include/lcx_sha512.h b/lib_cxng/include/lcx_sha512.h index 4d002e440..4b9790102 100644 --- a/lib_cxng/include/lcx_sha512.h +++ b/lib_cxng/include/lcx_sha512.h @@ -1,20 +1,20 @@ /******************************************************************************* -* Ledger Nano S - Secure firmware -* (c) 2022 Ledger -* -* Licensed under the Apache License, Version 2.0 (the "License"); -* you may not use this file except in compliance with the License. -* You may obtain a copy of the License at -* -* http://www.apache.org/licenses/LICENSE-2.0 -* -* Unless required by applicable law or agreed to in writing, software -* distributed under the License is distributed on an "AS IS" BASIS, -* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -* See the License for the specific language governing permissions and -* limitations under the License. -********************************************************************************/ + * Ledger Nano S - Secure firmware + * (c) 2022 Ledger + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + ********************************************************************************/ /** * @file lcx_sha512.h @@ -41,10 +41,10 @@ * @brief SHA-384 and SHA-512 context */ struct cx_sha512_s { - struct cx_hash_header_s header; ///< @copydoc cx_ripemd160_s::header - size_t blen; ///< @copydoc cx_ripemd160_s::blen - uint8_t block[128]; ///< @copydoc cx_ripemd160_s::block - uint8_t acc[8 * 8]; ///< @copydoc cx_ripemd160_s::acc + struct cx_hash_header_s header; ///< @copydoc cx_ripemd160_s::header + size_t blen; ///< @copydoc cx_ripemd160_s::blen + uint8_t block[128]; ///< @copydoc cx_ripemd160_s::block + uint8_t acc[8 * 8]; ///< @copydoc cx_ripemd160_s::acc }; /** Convenience type. See #cx_sha512_s. */ typedef struct cx_sha512_s cx_sha512_t; @@ -68,10 +68,10 @@ cx_err_t cx_sha384_init_no_throw(cx_sha512_t *hash); * * @return SHA384 identifier. */ -static inline int cx_sha384_init ( cx_sha512_t * hash ) +static inline int cx_sha384_init(cx_sha512_t *hash) { - cx_sha384_init_no_throw(hash); - return CX_SHA384; + cx_sha384_init_no_throw(hash); + return CX_SHA384; } /** @@ -93,10 +93,10 @@ cx_err_t cx_sha512_init_no_throw(cx_sha512_t *hash); * * @return SHA512 identifier. */ -static inline int cx_sha512_init ( cx_sha512_t * hash ) +static inline int cx_sha512_init(cx_sha512_t *hash) { - cx_sha512_init_no_throw(hash); - return CX_SHA512; + cx_sha512_init_no_throw(hash); + return CX_SHA512; } /** @@ -111,8 +111,8 @@ static inline int cx_sha512_init ( cx_sha512_t * hash ) * @param[out] out_len Length of the output. * This is actually 512 bits. */ - size_t cx_hash_sha512(const uint8_t *in, size_t in_len, uint8_t *out, size_t out_len); +size_t cx_hash_sha512(const uint8_t *in, size_t in_len, uint8_t *out, size_t out_len); #endif -#endif // defined(HAVE_SHA384) || defined(HAVE_SHA512) +#endif // defined(HAVE_SHA384) || defined(HAVE_SHA512) diff --git a/lib_cxng/include/lcx_wrappers.h b/lib_cxng/include/lcx_wrappers.h index 65955b195..1c81e8a3f 100644 --- a/lib_cxng/include/lcx_wrappers.h +++ b/lib_cxng/include/lcx_wrappers.h @@ -9,12 +9,13 @@ */ #include "exceptions.h" -#include "os_helpers.h" // for UNUSED +#include "os_helpers.h" // for UNUSED /* used by wrappers */ -#define CX_THROW(call) do { \ - cx_err_t error = call; \ - if (error) { \ - THROW(error); \ - } \ - } while (0) +#define CX_THROW(call) \ + do { \ + cx_err_t error = call; \ + if (error) { \ + THROW(error); \ + } \ + } while (0) diff --git a/lib_cxng/include/libcxng.h b/lib_cxng/include/libcxng.h index 20f73c0c6..62dbb5577 100644 --- a/lib_cxng/include/libcxng.h +++ b/lib_cxng/include/libcxng.h @@ -1,20 +1,20 @@ /******************************************************************************* -* Ledger Nano S - Secure firmware -* (c) 2022 Ledger -* -* Licensed under the Apache License, Version 2.0 (the "License"); -* you may not use this file except in compliance with the License. -* You may obtain a copy of the License at -* -* http://www.apache.org/licenses/LICENSE-2.0 -* -* Unless required by applicable law or agreed to in writing, software -* distributed under the License is distributed on an "AS IS" BASIS, -* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -* See the License for the specific language governing permissions and -* limitations under the License. -********************************************************************************/ + * Ledger Nano S - Secure firmware + * (c) 2022 Ledger + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + ********************************************************************************/ /** * @file libcxng.h diff --git a/lib_cxng/src/cx_Groestl-ref.c b/lib_cxng/src/cx_Groestl-ref.c index 2f236a09c..5310c301c 100644 --- a/lib_cxng/src/cx_Groestl-ref.c +++ b/lib_cxng/src/cx_Groestl-ref.c @@ -1,20 +1,20 @@ /******************************************************************************* -* Ledger Nano S - Secure firmware -* (c) 2022 Ledger -* -* Licensed under the Apache License, Version 2.0 (the "License"); -* you may not use this file except in compliance with the License. -* You may obtain a copy of the License at -* -* http://www.apache.org/licenses/LICENSE-2.0 -* -* Unless required by applicable law or agreed to in writing, software -* distributed under the License is distributed on an "AS IS" BASIS, -* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -* See the License for the specific language governing permissions and -* limitations under the License. -********************************************************************************/ + * Ledger Nano S - Secure firmware + * (c) 2022 Ledger + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + ********************************************************************************/ #ifdef HAVE_GROESTL @@ -26,59 +26,69 @@ #include "cx_Groestl-ref.h" static HashReturn Init(hashState *, int); -static void Update(hashState *, const BitSequence *, DataLength); -static void Final(hashState *, BitSequence *); - -cx_err_t cx_groestl_init_no_throw(cx_groestl_t *hash, size_t size) { - memset(hash, 0, sizeof(cx_groestl_t)); - switch (size) { - case 224: - case 256: - case 384: - case 512: - hash->output_size = size >> 3; - break; - default: - return CX_INVALID_PARAMETER; - } - - if (Init(&hash->ctx, size) != SUCCESS) { - return CX_INVALID_PARAMETER; - } - return CX_OK; +static void Update(hashState *, const BitSequence *, DataLength); +static void Final(hashState *, BitSequence *); + +cx_err_t cx_groestl_init_no_throw(cx_groestl_t *hash, size_t size) +{ + memset(hash, 0, sizeof(cx_groestl_t)); + switch (size) { + case 224: + case 256: + case 384: + case 512: + hash->output_size = size >> 3; + break; + default: + return CX_INVALID_PARAMETER; + } + + if (Init(&hash->ctx, size) != SUCCESS) { + return CX_INVALID_PARAMETER; + } + return CX_OK; } -cx_err_t cx_groestl(cx_groestl_t *hash, uint32_t mode, const uint8_t *in, size_t len, uint8_t *out, size_t out_len) { - size_t sz = 0; - Update(&((cx_groestl_t *)hash)->ctx, in, len); - if (mode & CX_LAST) { - sz = ((cx_groestl_t *)hash)->output_size; - if (out && (out_len < sz)) { - return CX_INVALID_PARAMETER; +cx_err_t cx_groestl(cx_groestl_t *hash, + uint32_t mode, + const uint8_t *in, + size_t len, + uint8_t *out, + size_t out_len) +{ + size_t sz = 0; + Update(&((cx_groestl_t *) hash)->ctx, in, len); + if (mode & CX_LAST) { + sz = ((cx_groestl_t *) hash)->output_size; + if (out && (out_len < sz)) { + return CX_INVALID_PARAMETER; + } + Final(&((cx_groestl_t *) hash)->ctx, out); } - Final(&((cx_groestl_t *)hash)->ctx, out); - } - return CX_OK; + return CX_OK; } -cx_err_t cx_groestl_update(cx_groestl_t *ctx, const uint8_t *data, size_t len) { - if (ctx == NULL) { - return CX_INVALID_PARAMETER; - } - if (data == NULL) { - return len == 0 ? CX_OK : CX_INVALID_PARAMETER; - } - Update(&ctx->ctx, data, len); - return CX_OK; +cx_err_t cx_groestl_update(cx_groestl_t *ctx, const uint8_t *data, size_t len) +{ + if (ctx == NULL) { + return CX_INVALID_PARAMETER; + } + if (data == NULL) { + return len == 0 ? CX_OK : CX_INVALID_PARAMETER; + } + Update(&ctx->ctx, data, len); + return CX_OK; } -cx_err_t cx_groestl_final(cx_groestl_t *ctx, uint8_t *digest) { - Final(&ctx->ctx, digest); - return CX_OK; +cx_err_t cx_groestl_final(cx_groestl_t *ctx, uint8_t *digest) +{ + Final(&ctx->ctx, digest); + return CX_OK; } -size_t cx_groestl_get_output_size(const cx_groestl_t *ctx) { - return ctx->output_size; +size_t cx_groestl_get_output_size(const cx_groestl_t *ctx) +{ + return ctx->output_size; } /* Groestl-ref.c January 2011 @@ -93,301 +103,327 @@ size_t cx_groestl_get_output_size(const cx_groestl_t *ctx) { /* S-box */ static const u8 S[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}; + 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}; /* Shift values for short/long variants */ -static const u8 Shift[2][2][ROWS] = {{{0, 1, 2, 3, 4, 5, 6, 7}, {1, 3, 5, 7, 0, 2, 4, 6}}, - {{0, 1, 2, 3, 4, 5, 6, 11}, {1, 3, 5, 11, 0, 2, 4, 6}}}; +static const u8 Shift[2][2][ROWS] = { + {{0, 1, 2, 3, 4, 5, 6, 7}, {1, 3, 5, 7, 0, 2, 4, 6} }, + {{0, 1, 2, 3, 4, 5, 6, 11}, {1, 3, 5, 11, 0, 2, 4, 6}} +}; /* AddRoundConstant xors a round-dependent constant to the state */ -static void AddRoundConstant(u8 x[ROWS][COLS1024], int columns, u8 round, Variant v) { - int i, j; - if ((v & 1) == 0) { - for (i = 0; i < columns; i++) - x[0][i] ^= (i << 4) ^ round; - } else { - for (i = 0; i < columns; i++) - for (j = 0; j < ROWS - 1; j++) - x[j][i] ^= 0xff; - for (i = 0; i < columns; i++) - x[ROWS - 1][i] ^= (i << 4) ^ 0xff ^ round; - } +static void AddRoundConstant(u8 x[ROWS][COLS1024], int columns, u8 round, Variant v) +{ + int i, j; + if ((v & 1) == 0) { + for (i = 0; i < columns; i++) { + x[0][i] ^= (i << 4) ^ round; + } + } + else { + for (i = 0; i < columns; i++) { + for (j = 0; j < ROWS - 1; j++) { + x[j][i] ^= 0xff; + } + } + for (i = 0; i < columns; i++) { + x[ROWS - 1][i] ^= (i << 4) ^ 0xff ^ round; + } + } } /* SubBytes replaces each byte by a value from the S-box */ -static void SubBytes(u8 x[ROWS][COLS1024], int columns) { - int i, j; +static void SubBytes(u8 x[ROWS][COLS1024], int columns) +{ + int i, j; - for (i = 0; i < ROWS; i++) - for (j = 0; j < columns; j++) - x[i][j] = S[x[i][j]]; + for (i = 0; i < ROWS; i++) { + for (j = 0; j < columns; j++) { + x[i][j] = S[x[i][j]]; + } + } } /* ShiftBytes cyclically shifts each row to the left by a number of positions */ -static void ShiftBytes(u8 x[ROWS][COLS1024], int columns, Variant v) { - const u8 *R = Shift[v / 2][v & 1]; - int i, j; - u8 temp[COLS1024]; - - for (i = 0; i < ROWS; i++) { - for (j = 0; j < columns; j++) { - temp[j] = x[i][(j + R[i]) % columns]; - } - for (j = 0; j < columns; j++) { - x[i][j] = temp[j]; +static void ShiftBytes(u8 x[ROWS][COLS1024], int columns, Variant v) +{ + const u8 *R = Shift[v / 2][v & 1]; + int i, j; + u8 temp[COLS1024]; + + for (i = 0; i < ROWS; i++) { + for (j = 0; j < columns; j++) { + temp[j] = x[i][(j + R[i]) % columns]; + } + for (j = 0; j < columns; j++) { + x[i][j] = temp[j]; + } } - } } /* MixBytes reversibly mixes the bytes within a column */ -static void MixBytes(u8 x[ROWS][COLS1024], int columns) { - int i, j; - u8 temp[ROWS]; - - for (i = 0; i < columns; i++) { - for (j = 0; j < ROWS; j++) { - temp[j] = mul2(x[(j + 0) % ROWS][i]) ^ mul2(x[(j + 1) % ROWS][i]) ^ mul3(x[(j + 2) % ROWS][i]) ^ - mul4(x[(j + 3) % ROWS][i]) ^ mul5(x[(j + 4) % ROWS][i]) ^ mul3(x[(j + 5) % ROWS][i]) ^ - mul5(x[(j + 6) % ROWS][i]) ^ mul7(x[(j + 7) % ROWS][i]); - } - for (j = 0; j < ROWS; j++) { - x[j][i] = temp[j]; +static void MixBytes(u8 x[ROWS][COLS1024], int columns) +{ + int i, j; + u8 temp[ROWS]; + + for (i = 0; i < columns; i++) { + for (j = 0; j < ROWS; j++) { + temp[j] = mul2(x[(j + 0) % ROWS][i]) ^ mul2(x[(j + 1) % ROWS][i]) + ^ mul3(x[(j + 2) % ROWS][i]) ^ mul4(x[(j + 3) % ROWS][i]) + ^ mul5(x[(j + 4) % ROWS][i]) ^ mul3(x[(j + 5) % ROWS][i]) + ^ mul5(x[(j + 6) % ROWS][i]) ^ mul7(x[(j + 7) % ROWS][i]); + } + for (j = 0; j < ROWS; j++) { + x[j][i] = temp[j]; + } } - } } /* apply P-permutation to x */ -static void P(hashState *ctx, u8 x[ROWS][COLS1024]) { - u8 i; - Variant v = ctx->columns == 8 ? P512 : P1024; - for (i = 0; i < ctx->rounds; i++) { - AddRoundConstant(x, ctx->columns, i, v); - SubBytes(x, ctx->columns); - ShiftBytes(x, ctx->columns, v); - MixBytes(x, ctx->columns); - } +static void P(hashState *ctx, u8 x[ROWS][COLS1024]) +{ + u8 i; + Variant v = ctx->columns == 8 ? P512 : P1024; + for (i = 0; i < ctx->rounds; i++) { + AddRoundConstant(x, ctx->columns, i, v); + SubBytes(x, ctx->columns); + ShiftBytes(x, ctx->columns, v); + MixBytes(x, ctx->columns); + } } /* apply Q-permutation to x */ -static void Q(hashState *ctx, u8 x[ROWS][COLS1024]) { - u8 i; - Variant v = ctx->columns == 8 ? Q512 : Q1024; - for (i = 0; i < ctx->rounds; i++) { - AddRoundConstant(x, ctx->columns, i, v); - SubBytes(x, ctx->columns); - ShiftBytes(x, ctx->columns, v); - MixBytes(x, ctx->columns); - } +static void Q(hashState *ctx, u8 x[ROWS][COLS1024]) +{ + u8 i; + Variant v = ctx->columns == 8 ? Q512 : Q1024; + for (i = 0; i < ctx->rounds; i++) { + AddRoundConstant(x, ctx->columns, i, v); + SubBytes(x, ctx->columns); + ShiftBytes(x, ctx->columns, v); + MixBytes(x, ctx->columns); + } } /* digest (up to) msglen bytes */ -static void Transform(hashState *ctx, const BitSequence *input, u32 msglen) { - unsigned int i, j; +static void Transform(hashState *ctx, const BitSequence *input, u32 msglen) +{ + unsigned int i, j; /* u8 temp1[ROWS][COLS1024], temp2[ROWS][COLS1024]; */ #define temp1 G_cx.groestl.temp1 #define temp2 G_cx.groestl.temp2 - /* digest one message block at the time */ - for (; msglen >= ctx->statesize; msglen -= ctx->statesize, input += ctx->statesize) { - /* store message block (m) in temp2, and xor of chaining (h) and - message block in temp1 */ - for (i = 0; i < ROWS; i++) { - for (j = 0; j < ctx->columns; j++) { - temp1[i][j] = ctx->chaining[i][j] ^ input[j * ROWS + i]; - temp2[i][j] = input[j * ROWS + i]; - } - } - - P(ctx, temp1); /* P(h+m) */ - Q(ctx, temp2); /* Q(m) */ - - /* xor P(h+m) and Q(m) onto chaining, yielding P(h+m)+Q(m)+h */ - for (i = 0; i < ROWS; i++) { - cx_memxor(ctx->chaining[i], temp1[i], ctx->columns); - cx_memxor(ctx->chaining[i], temp2[i], ctx->columns); - // for (j = 0; j < ctx->columns; j++) { - // ctx->chaining[i][j] ^= temp1[i][j] ^ temp2[i][j]; - // } + /* digest one message block at the time */ + for (; msglen >= ctx->statesize; msglen -= ctx->statesize, input += ctx->statesize) { + /* store message block (m) in temp2, and xor of chaining (h) and + message block in temp1 */ + for (i = 0; i < ROWS; i++) { + for (j = 0; j < ctx->columns; j++) { + temp1[i][j] = ctx->chaining[i][j] ^ input[j * ROWS + i]; + temp2[i][j] = input[j * ROWS + i]; + } + } + + P(ctx, temp1); /* P(h+m) */ + Q(ctx, temp2); /* Q(m) */ + + /* xor P(h+m) and Q(m) onto chaining, yielding P(h+m)+Q(m)+h */ + for (i = 0; i < ROWS; i++) { + cx_memxor(ctx->chaining[i], temp1[i], ctx->columns); + cx_memxor(ctx->chaining[i], temp2[i], ctx->columns); + // for (j = 0; j < ctx->columns; j++) { + // ctx->chaining[i][j] ^= temp1[i][j] ^ temp2[i][j]; + // } + } + + /* increment block counter */ + ctx->block_counter++; } - - /* increment block counter */ - ctx->block_counter++; - } #undef temp1 #undef temp2 } /* do output transformation, P(h)+h */ -static void OutputTransformation(hashState *ctx) { - unsigned int i, j; +static void OutputTransformation(hashState *ctx) +{ + unsigned int i, j; /* u8 temp[ROWS][COLS1024]; */ // OK because no used at the same time than tmp in Transform #define temp G_cx.groestl.temp1 - /* store chaining ("h") in temp */ - for (i = 0; i < ROWS; i++) { - for (j = 0; j < ctx->columns; j++) { - temp[i][j] = ctx->chaining[i][j]; + /* store chaining ("h") in temp */ + for (i = 0; i < ROWS; i++) { + for (j = 0; j < ctx->columns; j++) { + temp[i][j] = ctx->chaining[i][j]; + } + } + + /* compute P(temp) = P(h) */ + P(ctx, temp); + + /* feed chaining forward, yielding P(h)+h */ + for (i = 0; i < ROWS; i++) { + cx_memxor(ctx->chaining[i], temp[i], ctx->columns); + // for (j = 0; j < ctx->columns; j++) { + // ctx->chaining[i][j] ^= temp[i][j]; + // } } - } - - /* compute P(temp) = P(h) */ - P(ctx, temp); - - /* feed chaining forward, yielding P(h)+h */ - for (i = 0; i < ROWS; i++) { - cx_memxor(ctx->chaining[i], temp[i], ctx->columns); - // for (j = 0; j < ctx->columns; j++) { - // ctx->chaining[i][j] ^= temp[i][j]; - // } - } #undef temp } /* initialise context */ -static HashReturn Init(hashState *ctx, int hashbitlen) { - unsigned int i, j; - - if (hashbitlen <= 0 || (hashbitlen % 8) || hashbitlen > 512) - return BAD_HASHLEN; - - if (hashbitlen <= 256) { - ctx->rounds = ROUNDS512; - ctx->columns = COLS512; - ctx->statesize = SIZE512; - } else { - ctx->rounds = ROUNDS1024; - ctx->columns = COLS1024; - ctx->statesize = SIZE1024; - } - - /* zeroise chaining variable */ - for (i = 0; i < ROWS; i++) { - for (j = 0; j < ctx->columns; j++) { - ctx->chaining[i][j] = 0; +static HashReturn Init(hashState *ctx, int hashbitlen) +{ + unsigned int i, j; + + if (hashbitlen <= 0 || (hashbitlen % 8) || hashbitlen > 512) { + return BAD_HASHLEN; } - } - /* store hashbitlen and set initial value */ - ctx->hashlen = hashbitlen / 8u; - for (i = ROWS - sizeof(int); i < ROWS; i++) { - ctx->chaining[i][ctx->columns - 1] = (u8)(hashbitlen >> (8 * (7 - i))); - } + if (hashbitlen <= 256) { + ctx->rounds = ROUNDS512; + ctx->columns = COLS512; + ctx->statesize = SIZE512; + } + else { + ctx->rounds = ROUNDS1024; + ctx->columns = COLS1024; + ctx->statesize = SIZE1024; + } - /* initialise other variables */ - ctx->buf_ptr = 0; - ctx->block_counter = 0; + /* zeroise chaining variable */ + for (i = 0; i < ROWS; i++) { + for (j = 0; j < ctx->columns; j++) { + ctx->chaining[i][j] = 0; + } + } - return SUCCESS; -} + /* store hashbitlen and set initial value */ + ctx->hashlen = hashbitlen / 8u; + for (i = ROWS - sizeof(int); i < ROWS; i++) { + ctx->chaining[i][ctx->columns - 1] = (u8) (hashbitlen >> (8 * (7 - i))); + } -static void Update(hashState *ctx, const BitSequence *input, DataLength msglen) { - unsigned int index = 0; + /* initialise other variables */ + ctx->buf_ptr = 0; + ctx->block_counter = 0; - /* if the buffer contains data that still needs to be digested */ - if (ctx->buf_ptr) { - /* copy data into buffer until buffer is full, or there is no more - data */ - for (index = 0; ctx->buf_ptr < ctx->statesize && index < msglen; index++, ctx->buf_ptr++) { - ctx->buffer[ctx->buf_ptr] = input[index]; - } + return SUCCESS; +} - if (ctx->buf_ptr < ctx->statesize) { - /* this chunk of message does not fill the buffer */ - return; +static void Update(hashState *ctx, const BitSequence *input, DataLength msglen) +{ + unsigned int index = 0; + + /* if the buffer contains data that still needs to be digested */ + if (ctx->buf_ptr) { + /* copy data into buffer until buffer is full, or there is no more + data */ + for (index = 0; ctx->buf_ptr < ctx->statesize && index < msglen; index++, ctx->buf_ptr++) { + ctx->buffer[ctx->buf_ptr] = input[index]; + } + + if (ctx->buf_ptr < ctx->statesize) { + /* this chunk of message does not fill the buffer */ + return; + } + + /* the buffer is full, digest */ + ctx->buf_ptr = 0; + Transform(ctx, ctx->buffer, ctx->statesize); } - /* the buffer is full, digest */ - ctx->buf_ptr = 0; - Transform(ctx, ctx->buffer, ctx->statesize); - } - - /* digest remainder of data modulo the block size */ - Transform(ctx, input + index, msglen - index); - index += ((msglen - index) / ctx->statesize) * ctx->statesize; + /* digest remainder of data modulo the block size */ + Transform(ctx, input + index, msglen - index); + index += ((msglen - index) / ctx->statesize) * ctx->statesize; - /* copy remaining data to buffer */ - for (; index < msglen; index++, ctx->buf_ptr++) { - ctx->buffer[ctx->buf_ptr] = input[index]; - } - return; + /* copy remaining data to buffer */ + for (; index < msglen; index++, ctx->buf_ptr++) { + ctx->buffer[ctx->buf_ptr] = input[index]; + } + return; } -static void Final(hashState *ctx, BitSequence *output) { - unsigned int zeroise; - unsigned int i, j; - - /* 100... padding */ - ctx->buffer[ctx->buf_ptr++] = 0x80; +static void Final(hashState *ctx, BitSequence *output) +{ + unsigned int zeroise; + unsigned int i, j; + + /* 100... padding */ + ctx->buffer[ctx->buf_ptr++] = 0x80; + + if (ctx->buf_ptr > ctx->statesize - LENGTHFIELDLEN) { + /* padding requires two blocks */ + while (ctx->buf_ptr < ctx->statesize) { + ctx->buffer[ctx->buf_ptr++] = 0; + } + Transform(ctx, ctx->buffer, ctx->statesize); + ctx->buf_ptr = 0; + } + while (ctx->buf_ptr < ctx->statesize - LENGTHFIELDLEN) { + ctx->buffer[ctx->buf_ptr++] = 0; + } - if (ctx->buf_ptr > ctx->statesize - LENGTHFIELDLEN) { - /* padding requires two blocks */ - while (ctx->buf_ptr < ctx->statesize) { - ctx->buffer[ctx->buf_ptr++] = 0; + /* length padding */ + ctx->block_counter++; + ctx->buf_ptr = ctx->statesize; + while (ctx->buf_ptr > ctx->statesize - LENGTHFIELDLEN) { + ctx->buffer[--ctx->buf_ptr] = (u8) ctx->block_counter; + ctx->block_counter >>= 8; } + + /* digest (last) padding block */ Transform(ctx, ctx->buffer, ctx->statesize); - ctx->buf_ptr = 0; - } - while (ctx->buf_ptr < ctx->statesize - LENGTHFIELDLEN) { - ctx->buffer[ctx->buf_ptr++] = 0; - } - - /* length padding */ - ctx->block_counter++; - ctx->buf_ptr = ctx->statesize; - while (ctx->buf_ptr > ctx->statesize - LENGTHFIELDLEN) { - ctx->buffer[--ctx->buf_ptr] = (u8)ctx->block_counter; - ctx->block_counter >>= 8; - } - - /* digest (last) padding block */ - Transform(ctx, ctx->buffer, ctx->statesize); - /* output transformation */ - OutputTransformation(ctx); - - /* store hash output */ - if (output) { - zeroise = 1; - } else { - zeroise = 0; - output = ctx->buffer; - } - j = 0; - for (i = ctx->statesize - ctx->hashlen; i < ctx->statesize; i++, j++) { - output[j] = ctx->chaining[i % ROWS][i / ROWS]; - } - if (zeroise == 0) { - zeroise = j; - } - - /* zeroise */ - for (i = 0; i < ROWS; i++) { - for (j = 0; j < ctx->columns; j++) { - ctx->chaining[i][j] = 0; + /* output transformation */ + OutputTransformation(ctx); + + /* store hash output */ + if (output) { + zeroise = 1; + } + else { + zeroise = 0; + output = ctx->buffer; + } + j = 0; + for (i = ctx->statesize - ctx->hashlen; i < ctx->statesize; i++, j++) { + output[j] = ctx->chaining[i % ROWS][i / ROWS]; + } + if (zeroise == 0) { + zeroise = j; + } + + /* zeroise */ + for (i = 0; i < ROWS; i++) { + for (j = 0; j < ctx->columns; j++) { + ctx->chaining[i][j] = 0; + } } - } - for (i = zeroise; i < ctx->statesize; i++) { - ctx->buffer[i] = 0; - } + for (i = zeroise; i < ctx->statesize; i++) { + ctx->buffer[i] = 0; + } } -#endif // HAVE_GROESTL +#endif // HAVE_GROESTL diff --git a/lib_cxng/src/cx_Groestl-ref.h b/lib_cxng/src/cx_Groestl-ref.h index fa5afd5f9..c42598844 100644 --- a/lib_cxng/src/cx_Groestl-ref.h +++ b/lib_cxng/src/cx_Groestl-ref.h @@ -3,8 +3,8 @@ #ifndef __groestl_ref_h #define __groestl_ref_h -//#include -//#include +// #include +// #include #define NEED_UINT_64T /* **** @@ -153,29 +153,29 @@ typedef unsigned long long uint_64t; #if defined(DLL_EXPORT) #if defined(_MSC_VER) || defined(__INTEL_COMPILER) #define VOID_RETURN __declspec(dllexport) void __stdcall -#define INT_RETURN __declspec(dllexport) int __stdcall +#define INT_RETURN __declspec(dllexport) int __stdcall #elif defined(__GNUC__) #define VOID_RETURN __declspec(__dllexport__) void -#define INT_RETURN __declspec(__dllexport__) int +#define INT_RETURN __declspec(__dllexport__) int #else #error Use of the DLL is only available on the Microsoft, Intel and GCC compilers #endif #elif defined(DLL_IMPORT) #if defined(_MSC_VER) || defined(__INTEL_COMPILER) #define VOID_RETURN __declspec(dllimport) void __stdcall -#define INT_RETURN __declspec(dllimport) int __stdcall +#define INT_RETURN __declspec(dllimport) int __stdcall #elif defined(__GNUC__) #define VOID_RETURN __declspec(__dllimport__) void -#define INT_RETURN __declspec(__dllimport__) int +#define INT_RETURN __declspec(__dllimport__) int #else #error Use of the DLL is only available on the Microsoft, Intel and GCC compilers #endif #elif defined(__WATCOMC__) #define VOID_RETURN void __cdecl -#define INT_RETURN int __cdecl +#define INT_RETURN int __cdecl #else #define VOID_RETURN void -#define INT_RETURN int +#define INT_RETURN int #endif #endif @@ -198,9 +198,9 @@ typedef unsigned long long uint_64t; pointed to by 'x' ('n' is a power of 2) */ -#define ALIGN_OFFSET(x, n) (((ptrint_t)(x)) & ((n)-1)) -#define ALIGN_FLOOR(x, n) ((uint_8t *)(x) - (((ptrint_t)(x)) & ((n)-1))) -#define ALIGN_CEIL(x, n) ((uint_8t *)(x) + (-((ptrint_t)(x)) & ((n)-1))) +#define ALIGN_OFFSET(x, n) (((ptrint_t) (x)) & ((n) -1)) +#define ALIGN_FLOOR(x, n) ((uint_8t *) (x) - (((ptrint_t) (x)) & ((n) -1))) +#define ALIGN_CEIL(x, n) ((uint_8t *) (x) + (-((ptrint_t) (x)) & ((n) -1))) /* These defines are used to declare buffers in a way that allows faster operations on longer variables to be used. In all these @@ -222,14 +222,14 @@ typedef unsigned long long uint_64t; variable of length 'size' bits */ -#define UI_TYPE(size) uint_##size##t -#define UNIT_TYPEDEF(x, size) typedef UI_TYPE(size) x +#define UI_TYPE(size) uint_##size##t +#define UNIT_TYPEDEF(x, size) typedef UI_TYPE(size) x #define BUFR_TYPEDEF(x, size, bsize) typedef UI_TYPE(size) x[bsize / (size >> 3)] -#define UNIT_CAST(x, size) ((UI_TYPE(size))(x)) -#define UPTR_CAST(x, size) ((UI_TYPE(size) *)(x)) +#define UNIT_CAST(x, size) ((UI_TYPE(size))(x)) +#define UPTR_CAST(x, size) ((UI_TYPE(size) *) (x)) /* Added by Soeren S. Thomsen (begin) */ -#define u8 uint_8t +#define u8 uint_8t #define u32 uint_32t #define u64 uint_64t /* (end) */ @@ -240,19 +240,24 @@ typedef unsigned long long uint_64t; //End of inline **** */ -#define ROWS 8 +#define ROWS 8 #define LENGTHFIELDLEN ROWS -#define COLS512 8 -#define COLS1024 16 -#define SIZE512 (ROWS * COLS512) +#define COLS512 8 +#define COLS1024 16 +#define SIZE512 (ROWS * COLS512) // #define SIZE1024 (ROWS*COLS1024) -#define ROUNDS512 10 -#define ROUNDS1024 14 - -typedef enum { P512 = 0, Q512 = 1, P1024 = 2, Q1024 = 3 } Variant; - -#define mul1(b) ((u8)(b)) -#define mul2(b) ((u8)((b) >> 7 ? ((b) << 1) ^ 0x1b : ((b) << 1))) +#define ROUNDS512 10 +#define ROUNDS1024 14 + +typedef enum { + P512 = 0, + Q512 = 1, + P1024 = 2, + Q1024 = 3 +} Variant; + +#define mul1(b) ((u8) (b)) +#define mul2(b) ((u8) ((b) >> 7 ? ((b) << 1) ^ 0x1b : ((b) << 1))) #define mul3(b) (mul2(b) ^ mul1(b)) #define mul4(b) mul2(mul2(b)) #define mul5(b) (mul4(b) ^ mul1(b)) @@ -261,7 +266,11 @@ typedef enum { P512 = 0, Q512 = 1, P1024 = 2, Q1024 = 3 } Variant; /* NIST API begin */ typedef unsigned long long DataLength; -typedef enum { SUCCESS = 0, FAIL = 1, BAD_HASHLEN = 2 } HashReturn; +typedef enum { + SUCCESS = 0, + FAIL = 1, + BAD_HASHLEN = 2 +} HashReturn; /* NIST API end */ /* helper functions */ @@ -269,4 +278,4 @@ void PrintHash(BitSequence *, int); #endif /* __groestl_ref_h */ -#endif // HAVE_GROESTL +#endif // HAVE_GROESTL diff --git a/lib_cxng/src/cx_aead.c b/lib_cxng/src/cx_aead.c index e83c0b684..c5071cc94 100644 --- a/lib_cxng/src/cx_aead.c +++ b/lib_cxng/src/cx_aead.c @@ -1,20 +1,20 @@ /******************************************************************************* -* Ledger Nano S - Secure firmware -* (c) 2022 Ledger -* -* Licensed under the Apache License, Version 2.0 (the "License"); -* you may not use this file except in compliance with the License. -* You may obtain a copy of the License at -* -* http://www.apache.org/licenses/LICENSE-2.0 -* -* Unless required by applicable law or agreed to in writing, software -* distributed under the License is distributed on an "AS IS" BASIS, -* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -* See the License for the specific language governing permissions and -* limitations under the License. -********************************************************************************/ + * Ledger Nano S - Secure firmware + * (c) 2022 Ledger + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT 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(HAVE_AEAD) #include "lcx_aead.h" @@ -24,129 +24,150 @@ #if defined(HAVE_AES_GCM) #include "cx_aes_gcm.h" -#endif // HAVE_AES +#endif // HAVE_AES #if defined(HAVE_CHACHA_POLY) && defined(HAVE_CHACHA) && defined(HAVE_POLY1305) #include "cx_chacha_poly.h" #endif - -const cx_aead_info_t *cx_aead_get_info(cx_aead_type_t type) { - switch (type) { +const cx_aead_info_t *cx_aead_get_info(cx_aead_type_t type) +{ + switch (type) { #if defined(HAVE_AES_GCM) - case CX_AEAD_AES128_GCM: - return &cx_aes128_gcm_info; - case CX_AEAD_AES192_GCM: - return &cx_aes192_gcm_info; - case CX_AEAD_AES256_GCM: - return &cx_aes256_gcm_info; -#endif // HAVE_AES_GCM + case CX_AEAD_AES128_GCM: + return &cx_aes128_gcm_info; + case CX_AEAD_AES192_GCM: + return &cx_aes192_gcm_info; + case CX_AEAD_AES256_GCM: + return &cx_aes256_gcm_info; +#endif // HAVE_AES_GCM #if defined(HAVE_CHACHA_POLY) && defined(HAVE_CHACHA) && defined(HAVE_POLY1305) - case CX_AEAD_CHACHA20_POLY1305: - return &cx_chacha20_poly1305_info; + case CX_AEAD_CHACHA20_POLY1305: + return &cx_chacha20_poly1305_info; #endif - default: - return NULL; - } + default: + return NULL; + } } -cx_err_t cx_aead_init(cx_aead_context_t *ctx) { - if (NULL == ctx) { - return CX_INVALID_PARAMETER; - } - memset(ctx, 0, sizeof(cx_aead_context_t)); - return CX_OK; +cx_err_t cx_aead_init(cx_aead_context_t *ctx) +{ + if (NULL == ctx) { + return CX_INVALID_PARAMETER; + } + memset(ctx, 0, sizeof(cx_aead_context_t)); + return CX_OK; } -cx_err_t cx_aead_setup(cx_aead_context_t *ctx, cx_aead_type_t type) { - const cx_aead_info_t *info = cx_aead_get_info(type); - if (NULL == info) { - return CX_INVALID_PARAMETER; - } - ctx->info = info; - ctx->info->func->init(ctx->base_ctx); - return CX_OK; - +cx_err_t cx_aead_setup(cx_aead_context_t *ctx, cx_aead_type_t type) +{ + const cx_aead_info_t *info = cx_aead_get_info(type); + if (NULL == info) { + return CX_INVALID_PARAMETER; + } + ctx->info = info; + ctx->info->func->init(ctx->base_ctx); + return CX_OK; } -cx_err_t cx_aead_set_key(cx_aead_context_t *ctx, const uint8_t *key, size_t key_len, uint32_t mode) { - if (ctx->info->key_bitlen != key_len * 8) { - return CX_INVALID_PARAMETER_SIZE; - } - if ((mode != CX_ENCRYPT) && (mode != CX_DECRYPT)) { - return CX_INVALID_PARAMETER_VALUE; - } - ctx->mode = mode; - return ctx->info->func->set_key(ctx->base_ctx, key, key_len); - +cx_err_t cx_aead_set_key(cx_aead_context_t *ctx, const uint8_t *key, size_t key_len, uint32_t mode) +{ + if (ctx->info->key_bitlen != key_len * 8) { + return CX_INVALID_PARAMETER_SIZE; + } + if ((mode != CX_ENCRYPT) && (mode != CX_DECRYPT)) { + return CX_INVALID_PARAMETER_VALUE; + } + ctx->mode = mode; + return ctx->info->func->set_key(ctx->base_ctx, key, key_len); } -cx_err_t cx_aead_set_iv(cx_aead_context_t *ctx, const uint8_t *iv, size_t iv_len) { - if ((NULL == iv) || (iv_len < 1)) { - return CX_INVALID_PARAMETER; - } - if (NULL == ctx->info) { - return CX_INVALID_PARAMETER; - } - return ctx->info->func->start(ctx->base_ctx, ctx->mode, iv, iv_len); - +cx_err_t cx_aead_set_iv(cx_aead_context_t *ctx, const uint8_t *iv, size_t iv_len) +{ + if ((NULL == iv) || (iv_len < 1)) { + return CX_INVALID_PARAMETER; + } + if (NULL == ctx->info) { + return CX_INVALID_PARAMETER; + } + return ctx->info->func->start(ctx->base_ctx, ctx->mode, iv, iv_len); } -cx_err_t cx_aead_update_ad(cx_aead_context_t *ctx, const uint8_t *ad, size_t ad_len) { - if (NULL == ctx->info) { - return CX_INVALID_PARAMETER; - } - return ctx->info->func->update_aad(ctx->base_ctx, ad, ad_len); - +cx_err_t cx_aead_update_ad(cx_aead_context_t *ctx, const uint8_t *ad, size_t ad_len) +{ + if (NULL == ctx->info) { + return CX_INVALID_PARAMETER; + } + return ctx->info->func->update_aad(ctx->base_ctx, ad, ad_len); } -cx_err_t cx_aead_update(cx_aead_context_t *ctx, uint8_t *in, size_t in_len, uint8_t *out, size_t *out_len) { - if ((NULL == ctx->info) || (NULL == out_len)) { - return CX_INVALID_PARAMETER; - } - *out_len = in_len; - return ctx->info->func->update(ctx->base_ctx, in, out, in_len); - +cx_err_t cx_aead_update(cx_aead_context_t *ctx, + uint8_t *in, + size_t in_len, + uint8_t *out, + size_t *out_len) +{ + if ((NULL == ctx->info) || (NULL == out_len)) { + return CX_INVALID_PARAMETER; + } + *out_len = in_len; + return ctx->info->func->update(ctx->base_ctx, in, out, in_len); } -cx_err_t cx_aead_write_tag(cx_aead_context_t *ctx, uint8_t *tag, size_t tag_len) { - if ((NULL == ctx->info) || (NULL == tag)) { - return CX_INVALID_PARAMETER; - } - return ctx->info->func->finish(ctx->base_ctx, tag, tag_len); - +cx_err_t cx_aead_write_tag(cx_aead_context_t *ctx, uint8_t *tag, size_t tag_len) +{ + if ((NULL == ctx->info) || (NULL == tag)) { + return CX_INVALID_PARAMETER; + } + return ctx->info->func->finish(ctx->base_ctx, tag, tag_len); } -cx_err_t cx_aead_check_tag(cx_aead_context_t *ctx, const uint8_t *tag, size_t tag_len) { - - if ((NULL == ctx->info) || (ctx->mode != CX_DECRYPT)) { - return CX_INVALID_PARAMETER; - } +cx_err_t cx_aead_check_tag(cx_aead_context_t *ctx, const uint8_t *tag, size_t tag_len) +{ + if ((NULL == ctx->info) || (ctx->mode != CX_DECRYPT)) { + return CX_INVALID_PARAMETER; + } - return ctx->info->func->check_tag(ctx->base_ctx, tag, tag_len); + return ctx->info->func->check_tag(ctx->base_ctx, tag, tag_len); } -cx_err_t cx_aead_encrypt(cx_aead_context_t *ctx, const uint8_t *iv, size_t iv_len, - const uint8_t *ad, size_t ad_len, uint8_t *in, size_t in_len, - uint8_t *out, size_t *out_len, uint8_t *tag, size_t tag_len) { - if (NULL == ctx->info) { - return CX_INVALID_PARAMETER; - } - *out_len = in_len; - return ctx->info->func->encrypt_and_tag(ctx->base_ctx, in, in_len, iv, iv_len, - ad, ad_len, out, tag, tag_len); - +cx_err_t cx_aead_encrypt(cx_aead_context_t *ctx, + const uint8_t *iv, + size_t iv_len, + const uint8_t *ad, + size_t ad_len, + uint8_t *in, + size_t in_len, + uint8_t *out, + size_t *out_len, + uint8_t *tag, + size_t tag_len) +{ + if (NULL == ctx->info) { + return CX_INVALID_PARAMETER; + } + *out_len = in_len; + return ctx->info->func->encrypt_and_tag( + ctx->base_ctx, in, in_len, iv, iv_len, ad, ad_len, out, tag, tag_len); } -cx_err_t cx_aead_decrypt(cx_aead_context_t *ctx, const uint8_t *iv, size_t iv_len, - const uint8_t *ad, size_t ad_len, uint8_t *in, size_t in_len, - uint8_t *out, size_t *out_len, const uint8_t *tag, size_t tag_len) { - if (NULL == ctx->info) { - return CX_INVALID_PARAMETER; - } - *out_len = in_len; - return ctx->info->func->auth_decrypt(ctx->base_ctx, in, in_len, iv, iv_len, - ad, ad_len, out, tag, tag_len); - +cx_err_t cx_aead_decrypt(cx_aead_context_t *ctx, + const uint8_t *iv, + size_t iv_len, + const uint8_t *ad, + size_t ad_len, + uint8_t *in, + size_t in_len, + uint8_t *out, + size_t *out_len, + const uint8_t *tag, + size_t tag_len) +{ + if (NULL == ctx->info) { + return CX_INVALID_PARAMETER; + } + *out_len = in_len; + return ctx->info->func->auth_decrypt( + ctx->base_ctx, in, in_len, iv, iv_len, ad, ad_len, out, tag, tag_len); } -#endif // HAVE_AEAD +#endif // HAVE_AEAD diff --git a/lib_cxng/src/cx_aes.c b/lib_cxng/src/cx_aes.c index 6730183de..f008d5761 100644 --- a/lib_cxng/src/cx_aes.c +++ b/lib_cxng/src/cx_aes.c @@ -8,153 +8,167 @@ #include #include -cx_err_t cx_aes_init_key_no_throw(const uint8_t *raw_key, size_t key_len, cx_aes_key_t *key) { - memset(key, 0, sizeof(cx_aes_key_t)); - switch (key_len) { - case 16: - case 24: - case 32: - key->size = key_len; - memmove(key->keys, raw_key, key_len); - return CX_OK; - default: - return CX_INVALID_PARAMETER; - } +cx_err_t cx_aes_init_key_no_throw(const uint8_t *raw_key, size_t key_len, cx_aes_key_t *key) +{ + memset(key, 0, sizeof(cx_aes_key_t)); + switch (key_len) { + case 16: + case 24: + case 32: + key->size = key_len; + memmove(key->keys, raw_key, key_len); + return CX_OK; + default: + return CX_INVALID_PARAMETER; + } } -cx_err_t cx_aes_enc_block(const cx_aes_key_t *key, const uint8_t *inblock, uint8_t *outblock) { - cx_err_t error; - CX_CHECK(cx_aes_set_key_hw(key, CX_ENCRYPT)); - CX_CHECK(cx_aes_block_hw(inblock, outblock)); - cx_aes_reset_hw(); - end: +cx_err_t cx_aes_enc_block(const cx_aes_key_t *key, const uint8_t *inblock, uint8_t *outblock) +{ + cx_err_t error; + CX_CHECK(cx_aes_set_key_hw(key, CX_ENCRYPT)); + CX_CHECK(cx_aes_block_hw(inblock, outblock)); + cx_aes_reset_hw(); +end: return error; } -cx_err_t cx_aes_dec_block(const cx_aes_key_t *key, const uint8_t *inblock, uint8_t *outblock) { - cx_err_t error; - CX_CHECK(cx_aes_set_key_hw(key, CX_DECRYPT)); - CX_CHECK(cx_aes_block_hw(inblock, outblock)); - cx_aes_reset_hw(); - end: +cx_err_t cx_aes_dec_block(const cx_aes_key_t *key, const uint8_t *inblock, uint8_t *outblock) +{ + cx_err_t error; + CX_CHECK(cx_aes_set_key_hw(key, CX_DECRYPT)); + CX_CHECK(cx_aes_block_hw(inblock, outblock)); + cx_aes_reset_hw(); +end: return error; } cx_err_t cx_aes_iv_no_throw(const cx_aes_key_t *key, uint32_t mode, - const uint8_t * iv, + const uint8_t *iv, size_t iv_len, - const uint8_t * in, + const uint8_t *in, size_t in_len, - uint8_t * out, - size_t * out_len) { - cx_cipher_context_t *ctx; - cx_cipher_id_t type; - cx_err_t error; - uint32_t operation; - - switch (key->size) { - case 16: - type = CX_CIPHER_AES_128; - break; - case 24: - type = CX_CIPHER_AES_192; - break; - case 32: - type = CX_CIPHER_AES_256; - break; - default: - return CX_INVALID_PARAMETER; - } - - ctx = &G_cx.cipher; - operation = mode & CX_MASK_SIGCRYPT; - if ( (operation != CX_ENCRYPT) && (operation != CX_DECRYPT) - && (operation != CX_SIGN) && (operation != CX_VERIFY)) { - return CX_INVALID_PARAMETER_VALUE; - } - CX_CHECK(cx_cipher_init(ctx)); - // Set key - ctx->key_bitlen = key->size * 8; - ctx->operation = operation; - ctx->cipher_key = (const cipher_key_t*)key; - operation |= mode & CX_MASK_CHAIN; - CX_CHECK(cx_cipher_setup(ctx, type, mode & CX_MASK_CHAIN)); - CX_CHECK(cx_aes_set_key_hw(key, operation)); - CX_CHECK(cx_cipher_set_padding(ctx, mode & CX_MASK_PAD)); - CX_CHECK(cx_cipher_enc_dec(ctx, iv, iv_len, in, in_len, out, out_len)); - - end: + uint8_t *out, + size_t *out_len) +{ + cx_cipher_context_t *ctx; + cx_cipher_id_t type; + cx_err_t error; + uint32_t operation; + + switch (key->size) { + case 16: + type = CX_CIPHER_AES_128; + break; + case 24: + type = CX_CIPHER_AES_192; + break; + case 32: + type = CX_CIPHER_AES_256; + break; + default: + return CX_INVALID_PARAMETER; + } + + ctx = &G_cx.cipher; + operation = mode & CX_MASK_SIGCRYPT; + if ((operation != CX_ENCRYPT) && (operation != CX_DECRYPT) && (operation != CX_SIGN) + && (operation != CX_VERIFY)) { + return CX_INVALID_PARAMETER_VALUE; + } + CX_CHECK(cx_cipher_init(ctx)); + // Set key + ctx->key_bitlen = key->size * 8; + ctx->operation = operation; + ctx->cipher_key = (const cipher_key_t *) key; + operation |= mode & CX_MASK_CHAIN; + CX_CHECK(cx_cipher_setup(ctx, type, mode & CX_MASK_CHAIN)); + CX_CHECK(cx_aes_set_key_hw(key, operation)); + CX_CHECK(cx_cipher_set_padding(ctx, mode & CX_MASK_PAD)); + CX_CHECK(cx_cipher_enc_dec(ctx, iv, iv_len, in, in_len, out, out_len)); + +end: explicit_bzero(ctx, sizeof(cx_cipher_context_t)); return error; } -cx_err_t cx_aes_no_throw(const cx_aes_key_t *key, uint32_t mode, const uint8_t *in, size_t in_len, uint8_t *out, size_t *out_len) { - return cx_aes_iv_no_throw(key, mode, NULL, 0, in, in_len, out, out_len); +cx_err_t cx_aes_no_throw(const cx_aes_key_t *key, + uint32_t mode, + const uint8_t *in, + size_t in_len, + uint8_t *out, + size_t *out_len) +{ + return cx_aes_iv_no_throw(key, mode, NULL, 0, in, in_len, out, out_len); } -cx_err_t aes_ctr(cx_aes_key_t *ctx_key, size_t len, size_t *nc_off, uint8_t *nonce_counter, uint8_t *stream_block, - const uint8_t *input, uint8_t *output) { - uint8_t c; - size_t n = *nc_off; - cx_err_t error = CX_INVALID_PARAMETER; - UNUSED(ctx_key); - - while (len--) { - if (n == 0) { - CX_CHECK(cx_aes_block_hw(nonce_counter, stream_block)); - for (int i = CX_AES_BLOCK_SIZE; i > 0; i--) { - if (++nonce_counter[i - 1] != 0) { - break; - } +cx_err_t aes_ctr(cx_aes_key_t *ctx_key, + size_t len, + size_t *nc_off, + uint8_t *nonce_counter, + uint8_t *stream_block, + const uint8_t *input, + uint8_t *output) +{ + uint8_t c; + size_t n = *nc_off; + cx_err_t error = CX_INVALID_PARAMETER; + UNUSED(ctx_key); + + while (len--) { + if (n == 0) { + CX_CHECK(cx_aes_block_hw(nonce_counter, stream_block)); + for (int i = CX_AES_BLOCK_SIZE; i > 0; i--) { + if (++nonce_counter[i - 1] != 0) { + break; + } + } } + c = *input++; + *output++ = c ^ stream_block[n]; + n = (n + 1) & 0x0F; } - c = *input++; - *output++ = c ^ stream_block[n]; - n = (n + 1) & 0x0F; - } - *nc_off = n; - error = CX_OK; - - end: + *nc_off = n; + error = CX_OK; + +end: return error; } -cx_err_t aes_setkey(cx_aes_key_t *ctx_key, uint32_t operation, const uint8_t *key, uint32_t key_bitlen) { - cx_err_t error; - CX_CHECK(cx_aes_init_key_no_throw(key, key_bitlen/8, ctx_key)); - CX_CHECK(cx_aes_set_key_hw(ctx_key, operation)); - end: +cx_err_t aes_setkey(cx_aes_key_t *ctx_key, + uint32_t operation, + const uint8_t *key, + uint32_t key_bitlen) +{ + cx_err_t error; + CX_CHECK(cx_aes_init_key_no_throw(key, key_bitlen / 8, ctx_key)); + CX_CHECK(cx_aes_set_key_hw(ctx_key, operation)); +end: return error; } static const cx_cipher_base_t aes_base = { - (cx_err_t (*) (const uint8_t *inblock, uint8_t *outblock))cx_aes_block_hw, - (cx_err_t (*) (const uint8_t *inblock, uint8_t *outblock))cx_aes_block_hw, - (cx_err_t(*) (const cipher_key_t *ctx_key, size_t len, size_t *nc_off, uint8_t *nonce_counter, uint8_t *stream_block, const uint8_t *input, uint8_t *output))aes_ctr, - (cx_err_t(*) (const cipher_key_t *ctx_key, uint32_t operation, const uint8_t *key, uint32_t key_bitlen))aes_setkey, - (cx_err_t(*)(void))cx_aes_reset_hw, + (cx_err_t(*)(const uint8_t *inblock, uint8_t *outblock)) cx_aes_block_hw, + (cx_err_t(*)(const uint8_t *inblock, uint8_t *outblock)) cx_aes_block_hw, + (cx_err_t(*)(const cipher_key_t *ctx_key, + size_t len, + size_t *nc_off, + uint8_t *nonce_counter, + uint8_t *stream_block, + const uint8_t *input, + uint8_t *output)) aes_ctr, + (cx_err_t(*)(const cipher_key_t *ctx_key, + uint32_t operation, + const uint8_t *key, + uint32_t key_bitlen)) aes_setkey, + (cx_err_t(*)(void)) cx_aes_reset_hw, }; -const cx_cipher_info_t cx_aes_128_info = { - 128, - 16, - CX_AES_BLOCK_SIZE, - &aes_base -}; +const cx_cipher_info_t cx_aes_128_info = {128, 16, CX_AES_BLOCK_SIZE, &aes_base}; -const cx_cipher_info_t cx_aes_192_info = { - 192, - 16, - CX_AES_BLOCK_SIZE, - &aes_base -}; +const cx_cipher_info_t cx_aes_192_info = {192, 16, CX_AES_BLOCK_SIZE, &aes_base}; -const cx_cipher_info_t cx_aes_256_info = { - 256, - 16, - CX_AES_BLOCK_SIZE, - &aes_base -}; +const cx_cipher_info_t cx_aes_256_info = {256, 16, CX_AES_BLOCK_SIZE, &aes_base}; -#endif // HAVE_AES +#endif // HAVE_AES diff --git a/lib_cxng/src/cx_aes_gcm.c b/lib_cxng/src/cx_aes_gcm.c index 692abcd58..a1458f684 100644 --- a/lib_cxng/src/cx_aes_gcm.c +++ b/lib_cxng/src/cx_aes_gcm.c @@ -1,20 +1,20 @@ /******************************************************************************* -* Ledger Nano S - Secure firmware -* (c) 2022 Ledger -* -* Licensed under the Apache License, Version 2.0 (the "License"); -* you may not use this file except in compliance with the License. -* You may obtain a copy of the License at -* -* http://www.apache.org/licenses/LICENSE-2.0 -* -* Unless required by applicable law or agreed to in writing, software -* distributed under the License is distributed on an "AS IS" BASIS, -* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -* See the License for the specific language governing permissions and -* limitations under the License. -********************************************************************************/ + * Ledger Nano S - Secure firmware + * (c) 2022 Ledger + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT 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(HAVE_AES_GCM) && defined(HAVE_AES) @@ -23,7 +23,7 @@ #include "lcx_aes_gcm.h" #if defined(HAVE_AEAD) #include "lcx_aead.h" -#endif // HAVE_AEAD +#endif // HAVE_AEAD #include "cx_utils.h" #include "os_math.h" #include "ox_bn.h" @@ -36,48 +36,59 @@ #if defined(HAVE_AEAD) static const cx_aead_base_t cx_aes_gcm_functions = { - (void (*) (void *ctx))cx_aes_gcm_init, - (cx_err_t(*) (void *ctx, const uint8_t *key, size_t key_len))cx_aes_gcm_set_key, - (cx_err_t(*) (void *ctx, uint32_t mode, const uint8_t *iv, size_t iv_len))cx_aes_gcm_start, - (cx_err_t(*) (void *ctx, const uint8_t *aad, size_t aad_len))cx_aes_gcm_update_aad, - (cx_err_t(*) (void *ctx, const uint8_t *input, uint8_t *output, size_t len))cx_aes_gcm_update, - (cx_err_t(*) (void *ctx, uint8_t *tag, size_t tag_len))cx_aes_gcm_finish, - (cx_err_t(*) (void *ctx, const uint8_t *input, size_t len, - const uint8_t *iv, size_t iv_len, - const uint8_t *aad, size_t aad_len, - uint8_t *output, uint8_t *tag, size_t tag_len))cx_aes_gcm_encrypt_and_tag, - (cx_err_t(*) (void *ctx, const uint8_t *input, size_t len, - const uint8_t *iv, size_t iv_len, - const uint8_t *aad, size_t aad_len, - uint8_t *output, const uint8_t *tag, size_t tag_len))cx_aes_gcm_decrypt_and_auth, - (cx_err_t(*) (void *ctx, const uint8_t *tag, size_t tag_len))cx_aes_gcm_check_tag -}; - -const cx_aead_info_t cx_aes128_gcm_info = { - CX_AEAD_AES128_GCM, - 128, - 128, - &cx_aes_gcm_functions -}; - -const cx_aead_info_t cx_aes192_gcm_info = { - CX_AEAD_AES192_GCM, - 192, - 128, - &cx_aes_gcm_functions -}; - -const cx_aead_info_t cx_aes256_gcm_info = { - CX_AEAD_AES256_GCM, - 256, - 128, - &cx_aes_gcm_functions -}; -#endif // HAVE_AEAD + (void (*)(void *ctx)) cx_aes_gcm_init, + (cx_err_t(*)(void *ctx, const uint8_t *key, size_t key_len)) cx_aes_gcm_set_key, + (cx_err_t(*)(void *ctx, uint32_t mode, const uint8_t *iv, size_t iv_len)) cx_aes_gcm_start, + (cx_err_t(*)(void *ctx, const uint8_t *aad, size_t aad_len)) cx_aes_gcm_update_aad, + (cx_err_t(*)(void *ctx, const uint8_t *input, uint8_t *output, size_t len)) cx_aes_gcm_update, + (cx_err_t(*)(void *ctx, uint8_t *tag, size_t tag_len)) cx_aes_gcm_finish, + (cx_err_t(*)(void *ctx, + const uint8_t *input, + size_t len, + const uint8_t *iv, + size_t iv_len, + const uint8_t *aad, + size_t aad_len, + uint8_t *output, + uint8_t *tag, + size_t tag_len)) cx_aes_gcm_encrypt_and_tag, + (cx_err_t(*)(void *ctx, + const uint8_t *input, + size_t len, + const uint8_t *iv, + size_t iv_len, + const uint8_t *aad, + size_t aad_len, + uint8_t *output, + const uint8_t *tag, + size_t tag_len)) cx_aes_gcm_decrypt_and_auth, + (cx_err_t(*)(void *ctx, const uint8_t *tag, size_t tag_len)) cx_aes_gcm_check_tag}; + +const cx_aead_info_t cx_aes128_gcm_info = {CX_AEAD_AES128_GCM, 128, 128, &cx_aes_gcm_functions}; + +const cx_aead_info_t cx_aes192_gcm_info = {CX_AEAD_AES192_GCM, 192, 128, &cx_aes_gcm_functions}; + +const cx_aead_info_t cx_aes256_gcm_info = {CX_AEAD_AES256_GCM, 256, 128, &cx_aes_gcm_functions}; +#endif // HAVE_AEAD // The irreducible polynomial N(x) = x^128 + x^7 + x^2 + x + 1 -const uint8_t N[17] = {0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x87}; +const uint8_t N[17] = {0x01, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x87}; // 2nd Montgomery constant: R2 = x^(2*t*128) mod N(x) // t = 2 since the number of bytes of R is 17. @@ -87,15 +98,16 @@ const uint8_t R2[4] = {0x10, 0x00, 0x01, 0x11}; * Increments the right-most 32 bits of the block. * The left-most 96 bits remain unchanged. */ -static void cx_gcm_increment(uint8_t *in) { - size_t i; - - for (i = 0; i < 4; i++) { - // Increment the current byte and propagate the carry if necessary. - if (++(in[15 - i]) != 0) { - break; +static void cx_gcm_increment(uint8_t *in) +{ + size_t i; + + for (i = 0; i < 4; i++) { + // Increment the current byte and propagate the carry if necessary. + if (++(in[15 - i]) != 0) { + break; + } } - } } /** @@ -105,252 +117,287 @@ static void cx_gcm_increment(uint8_t *in) { * Given a 128*m-bit (hash) key H, for any 128*m-bit input X * It calculates a 128 bit output R = X0 * H0 + X1 * H1 + ... + X_{m-1} * H_{m-1}. */ -static void cx_gcm_xor_block(uint8_t *r, const uint8_t *a, const uint8_t *b, size_t len) { - size_t i; +static void cx_gcm_xor_block(uint8_t *r, const uint8_t *a, const uint8_t *b, size_t len) +{ + size_t i; - for (i = 0; i < len; i++) { - r[i] = a[i] ^ b[i]; - } + for (i = 0; i < len; i++) { + r[i] = a[i] ^ b[i]; + } } /** * Reverse bit order in an octet. */ -static uint8_t cx_reverse_8bits(uint8_t value) { - - value = ((value & 0xF0) >> 4) | ((value & 0x0F) << 4); - value = ((value & 0xCC) >> 2) | ((value & 0x33) << 2); - value = ((value & 0xAA) >> 1) | ((value & 0x55) << 1); +static uint8_t cx_reverse_8bits(uint8_t value) +{ + value = ((value & 0xF0) >> 4) | ((value & 0x0F) << 4); + value = ((value & 0xCC) >> 2) | ((value & 0x33) << 2); + value = ((value & 0xAA) >> 1) | ((value & 0x55) << 1); - return value; + return value; } /** * Reverse bit order in an array of octets. */ -static void cx_reverse_buffer(uint8_t *r, uint8_t *buf, size_t buf_len) { - size_t i; +static void cx_reverse_buffer(uint8_t *r, uint8_t *buf, size_t buf_len) +{ + size_t i; - for (i = 0; i < buf_len; i++) { - r[i] = cx_reverse_8bits(buf[buf_len - 1 - i]); - } + for (i = 0; i < buf_len; i++) { + r[i] = cx_reverse_8bits(buf[buf_len - 1 - i]); + } } /** * Multiplication over GF(2^128) using Nescrypt */ -static cx_err_t cx_gcm_mul(uint8_t *r, uint8_t *a, uint8_t *b) { - cx_err_t error; - cx_bn_t bn_n, bn_c, bn_a, bn_b, bn_r; - uint8_t tmp[AES_BLOCK_BYTES]; - - CX_CHECK(cx_bn_lock(GF2_128_MPI_BYTES, 0)); - CX_CHECK(cx_bn_alloc(&bn_r, GF2_128_MPI_BYTES)); - cx_reverse_buffer(tmp, a, AES_BLOCK_BYTES); - CX_CHECK(cx_bn_alloc_init(&bn_a, GF2_128_MPI_BYTES, tmp, AES_BLOCK_BYTES)); - cx_reverse_buffer(tmp, b, AES_BLOCK_BYTES); - CX_CHECK(cx_bn_alloc_init(&bn_b, GF2_128_MPI_BYTES, tmp, AES_BLOCK_BYTES)); - CX_CHECK(cx_bn_alloc_init(&bn_n, GF2_128_MPI_BYTES, N, sizeof(N))); - CX_CHECK(cx_bn_alloc_init(&bn_c, GF2_128_MPI_BYTES, R2, sizeof(R2))); - CX_CHECK(cx_bn_gf2_n_mul(bn_r, bn_b, bn_a, bn_n, bn_c)); - CX_CHECK(cx_bn_export(bn_r, tmp, AES_BLOCK_BYTES)); - cx_reverse_buffer(r, tmp, AES_BLOCK_BYTES); - - end: +static cx_err_t cx_gcm_mul(uint8_t *r, uint8_t *a, uint8_t *b) +{ + cx_err_t error; + cx_bn_t bn_n, bn_c, bn_a, bn_b, bn_r; + uint8_t tmp[AES_BLOCK_BYTES]; + + CX_CHECK(cx_bn_lock(GF2_128_MPI_BYTES, 0)); + CX_CHECK(cx_bn_alloc(&bn_r, GF2_128_MPI_BYTES)); + cx_reverse_buffer(tmp, a, AES_BLOCK_BYTES); + CX_CHECK(cx_bn_alloc_init(&bn_a, GF2_128_MPI_BYTES, tmp, AES_BLOCK_BYTES)); + cx_reverse_buffer(tmp, b, AES_BLOCK_BYTES); + CX_CHECK(cx_bn_alloc_init(&bn_b, GF2_128_MPI_BYTES, tmp, AES_BLOCK_BYTES)); + CX_CHECK(cx_bn_alloc_init(&bn_n, GF2_128_MPI_BYTES, N, sizeof(N))); + CX_CHECK(cx_bn_alloc_init(&bn_c, GF2_128_MPI_BYTES, R2, sizeof(R2))); + CX_CHECK(cx_bn_gf2_n_mul(bn_r, bn_b, bn_a, bn_n, bn_c)); + CX_CHECK(cx_bn_export(bn_r, tmp, AES_BLOCK_BYTES)); + cx_reverse_buffer(r, tmp, AES_BLOCK_BYTES); + +end: cx_bn_unlock(); return error; } -void cx_aes_gcm_init(cx_aes_gcm_context_t *ctx) { - memset(ctx, 0, sizeof(cx_aes_gcm_context_t)); +void cx_aes_gcm_init(cx_aes_gcm_context_t *ctx) +{ + memset(ctx, 0, sizeof(cx_aes_gcm_context_t)); } -cx_err_t cx_aes_gcm_set_key(cx_aes_gcm_context_t *ctx, const uint8_t *raw_key, size_t key_len) { - return cx_aes_init_key_no_throw(raw_key, key_len, &ctx->key); +cx_err_t cx_aes_gcm_set_key(cx_aes_gcm_context_t *ctx, const uint8_t *raw_key, size_t key_len) +{ + return cx_aes_init_key_no_throw(raw_key, key_len, &ctx->key); } -cx_err_t cx_aes_gcm_start(cx_aes_gcm_context_t *ctx, uint32_t mode, - const uint8_t *iv, size_t iv_len) { - - cx_err_t error = CX_INVALID_PARAMETER; - size_t i, block_len; +cx_err_t cx_aes_gcm_start(cx_aes_gcm_context_t *ctx, + uint32_t mode, + const uint8_t *iv, + size_t iv_len) +{ + cx_err_t error = CX_INVALID_PARAMETER; + size_t i, block_len; - if ((NULL == iv) || (iv_len < 1)) { - return CX_INVALID_PARAMETER; - } + if ((NULL == iv) || (iv_len < 1)) { + return CX_INVALID_PARAMETER; + } - ctx->mode = mode; - if (!ctx->flag) { - memset(ctx->enc_block, 0, AES_BLOCK_BYTES); + ctx->mode = mode; + if (!ctx->flag) { + memset(ctx->enc_block, 0, AES_BLOCK_BYTES); - // Compute H = AES_K(0) - CX_CHECK(cx_aes_enc_block(&ctx->key, ctx->enc_block, ctx->hash_key)); - memset(ctx->J0, 0, 16); + // Compute H = AES_K(0) + CX_CHECK(cx_aes_enc_block(&ctx->key, ctx->enc_block, ctx->hash_key)); + memset(ctx->J0, 0, 16); - // J0 = (IV|0|1) - if (12 == iv_len) { - memcpy(ctx->J0, iv, iv_len); - STORE32BE(1, ctx->J0 + 12); - } - // J0 = GHASH_H(IV|0^(s+64)|[len(IV)]_64) - else { - i = iv_len; - while (i > 0) { - block_len = MIN(i, AES_BLOCK_BYTES); - cx_gcm_xor_block(ctx->J0, ctx->J0, iv, block_len); - CX_CHECK(cx_gcm_mul(ctx->J0, ctx->hash_key, ctx->J0)); - iv += block_len; - i -= block_len; - } - memset(ctx->enc_block, 0, 8); - STORE64BE(iv_len * 8, ctx->enc_block + 8); - cx_gcm_xor_block(ctx->J0, ctx->J0, ctx->enc_block, AES_BLOCK_BYTES); - CX_CHECK(cx_gcm_mul(ctx->J0, ctx->hash_key, ctx->J0)); + // J0 = (IV|0|1) + if (12 == iv_len) { + memcpy(ctx->J0, iv, iv_len); + STORE32BE(1, ctx->J0 + 12); + } + // J0 = GHASH_H(IV|0^(s+64)|[len(IV)]_64) + else { + i = iv_len; + while (i > 0) { + block_len = MIN(i, AES_BLOCK_BYTES); + cx_gcm_xor_block(ctx->J0, ctx->J0, iv, block_len); + CX_CHECK(cx_gcm_mul(ctx->J0, ctx->hash_key, ctx->J0)); + iv += block_len; + i -= block_len; + } + memset(ctx->enc_block, 0, 8); + STORE64BE(iv_len * 8, ctx->enc_block + 8); + cx_gcm_xor_block(ctx->J0, ctx->J0, ctx->enc_block, AES_BLOCK_BYTES); + CX_CHECK(cx_gcm_mul(ctx->J0, ctx->hash_key, ctx->J0)); + } + // Save ctx->buf for cx_aes_gcm_finish + CX_CHECK(cx_aes_enc_block(&ctx->key, ctx->J0, ctx->enc_block)); + ctx->flag = 1; } - // Save ctx->buf for cx_aes_gcm_finish - CX_CHECK(cx_aes_enc_block(&ctx->key, ctx->J0, ctx->enc_block)); - ctx->flag = 1; - } - - error = CX_OK; - end: - return error; -} -cx_err_t cx_aes_gcm_update_aad(cx_aes_gcm_context_t *ctx, const uint8_t *aad, size_t aad_len) { - size_t i, block_len; - cx_err_t error = CX_OK; - // Process additional data - // Save for cx_aes_gcm_finish - ctx->aad_len += aad_len; - i = aad_len; - while (i > 0) { - block_len = MIN(i, AES_BLOCK_BYTES); - cx_gcm_xor_block(ctx->processed, ctx->processed, aad, block_len); - CX_CHECK(cx_gcm_mul(ctx->processed, ctx->hash_key, ctx->processed)); - aad += block_len; - i -= block_len; - } - end: + error = CX_OK; +end: return error; } -cx_err_t cx_aes_gcm_update(cx_aes_gcm_context_t *ctx, const uint8_t *in, uint8_t *out, size_t len) { - cx_err_t error = CX_INVALID_PARAMETER; - size_t i, block_len; - uint8_t tmp[AES_BLOCK_BYTES]; - - ctx->len += len; - i = len; - switch (ctx->mode) { - case CX_ENCRYPT: - while (i > 0) { +cx_err_t cx_aes_gcm_update_aad(cx_aes_gcm_context_t *ctx, const uint8_t *aad, size_t aad_len) +{ + size_t i, block_len; + cx_err_t error = CX_OK; + // Process additional data + // Save for cx_aes_gcm_finish + ctx->aad_len += aad_len; + i = aad_len; + while (i > 0) { block_len = MIN(i, AES_BLOCK_BYTES); - cx_gcm_increment(ctx->J0); - CX_CHECK(cx_aes_enc_block(&ctx->key, ctx->J0, tmp)); - cx_gcm_xor_block(out, in, tmp, block_len); - cx_gcm_xor_block(ctx->processed, ctx->processed, out, block_len); + cx_gcm_xor_block(ctx->processed, ctx->processed, aad, block_len); CX_CHECK(cx_gcm_mul(ctx->processed, ctx->hash_key, ctx->processed)); - if (i - block_len > 0) { - in += block_len; - out += block_len; - } - i -= block_len; - } - break; - case CX_DECRYPT: - while (i > 0) { - block_len = MIN(i, AES_BLOCK_BYTES); - cx_gcm_xor_block(ctx->processed, ctx->processed, in, block_len); - CX_CHECK(cx_gcm_mul(ctx->processed, ctx->hash_key, ctx->processed)); - cx_gcm_increment(ctx->J0); - CX_CHECK(cx_aes_enc_block(&ctx->key, ctx->J0, tmp)); - cx_gcm_xor_block(out, in, tmp, block_len); - if (i - block_len > 0) { - out += block_len; - in += block_len; - } + aad += block_len; i -= block_len; - } - break; - default: - return CX_INVALID_PARAMETER_VALUE; - } - error = CX_OK; - end: + } +end: return error; } -cx_err_t cx_aes_gcm_finish(cx_aes_gcm_context_t *ctx, uint8_t *tag, size_t tag_len) { - cx_err_t error; - - STORE64BE(ctx->aad_len * 8, ctx->J0); - STORE64BE(ctx->len * 8, ctx->J0 + 8); - cx_gcm_xor_block(ctx->processed, ctx->processed, ctx->J0, AES_BLOCK_BYTES); - CX_CHECK(cx_gcm_mul(ctx->processed, ctx->hash_key, ctx->processed)); - cx_gcm_xor_block(tag, ctx->enc_block, ctx->processed, tag_len); - - end: +cx_err_t cx_aes_gcm_update(cx_aes_gcm_context_t *ctx, const uint8_t *in, uint8_t *out, size_t len) +{ + cx_err_t error = CX_INVALID_PARAMETER; + size_t i, block_len; + uint8_t tmp[AES_BLOCK_BYTES]; + + ctx->len += len; + i = len; + switch (ctx->mode) { + case CX_ENCRYPT: + while (i > 0) { + block_len = MIN(i, AES_BLOCK_BYTES); + cx_gcm_increment(ctx->J0); + CX_CHECK(cx_aes_enc_block(&ctx->key, ctx->J0, tmp)); + cx_gcm_xor_block(out, in, tmp, block_len); + cx_gcm_xor_block(ctx->processed, ctx->processed, out, block_len); + CX_CHECK(cx_gcm_mul(ctx->processed, ctx->hash_key, ctx->processed)); + if (i - block_len > 0) { + in += block_len; + out += block_len; + } + i -= block_len; + } + break; + case CX_DECRYPT: + while (i > 0) { + block_len = MIN(i, AES_BLOCK_BYTES); + cx_gcm_xor_block(ctx->processed, ctx->processed, in, block_len); + CX_CHECK(cx_gcm_mul(ctx->processed, ctx->hash_key, ctx->processed)); + cx_gcm_increment(ctx->J0); + CX_CHECK(cx_aes_enc_block(&ctx->key, ctx->J0, tmp)); + cx_gcm_xor_block(out, in, tmp, block_len); + if (i - block_len > 0) { + out += block_len; + in += block_len; + } + i -= block_len; + } + break; + default: + return CX_INVALID_PARAMETER_VALUE; + } + error = CX_OK; +end: return error; } -static cx_err_t cx_aes_gcm_process_and_tag(cx_aes_gcm_context_t *ctx, uint32_t mode, uint8_t *in, size_t len, - const uint8_t *iv, size_t iv_len, const uint8_t *aad, size_t aad_len, - uint8_t *out, uint8_t *tag, size_t tag_len) { - cx_err_t error; +cx_err_t cx_aes_gcm_finish(cx_aes_gcm_context_t *ctx, uint8_t *tag, size_t tag_len) +{ + cx_err_t error; - CX_CHECK(cx_aes_gcm_start(ctx, mode, iv, iv_len)); - CX_CHECK(cx_aes_gcm_update_aad(ctx, aad, aad_len)); - CX_CHECK(cx_aes_gcm_update(ctx, in, out, len)); - CX_CHECK(cx_aes_gcm_finish(ctx, tag, tag_len)); + STORE64BE(ctx->aad_len * 8, ctx->J0); + STORE64BE(ctx->len * 8, ctx->J0 + 8); + cx_gcm_xor_block(ctx->processed, ctx->processed, ctx->J0, AES_BLOCK_BYTES); + CX_CHECK(cx_gcm_mul(ctx->processed, ctx->hash_key, ctx->processed)); + cx_gcm_xor_block(tag, ctx->enc_block, ctx->processed, tag_len); - end: +end: return error; } -cx_err_t cx_aes_gcm_encrypt_and_tag(cx_aes_gcm_context_t *ctx, uint8_t *in, size_t len, - const uint8_t *iv, size_t iv_len, const uint8_t *aad, size_t aad_len, - uint8_t *out, uint8_t *tag, size_t tag_len) { - return cx_aes_gcm_process_and_tag(ctx, CX_ENCRYPT, in, len, iv, iv_len, aad, aad_len, - out, tag, tag_len); +static cx_err_t cx_aes_gcm_process_and_tag(cx_aes_gcm_context_t *ctx, + uint32_t mode, + uint8_t *in, + size_t len, + const uint8_t *iv, + size_t iv_len, + const uint8_t *aad, + size_t aad_len, + uint8_t *out, + uint8_t *tag, + size_t tag_len) +{ + cx_err_t error; + + CX_CHECK(cx_aes_gcm_start(ctx, mode, iv, iv_len)); + CX_CHECK(cx_aes_gcm_update_aad(ctx, aad, aad_len)); + CX_CHECK(cx_aes_gcm_update(ctx, in, out, len)); + CX_CHECK(cx_aes_gcm_finish(ctx, tag, tag_len)); + +end: + return error; } -cx_err_t cx_aes_gcm_decrypt_and_auth(cx_aes_gcm_context_t *ctx, uint8_t *in, size_t len, - const uint8_t *iv, size_t iv_len, const uint8_t *aad, - size_t aad_len, uint8_t *out, const uint8_t *tag, size_t tag_len) { - - cx_err_t error; - uint8_t check_tag[AES_BLOCK_BYTES]; - uint8_t diff; - - CX_CHECK(cx_aes_gcm_process_and_tag(ctx, CX_DECRYPT, in, len, iv, iv_len, - aad, aad_len, out, check_tag, tag_len)); - diff = cx_constant_time_eq(tag, check_tag, tag_len); - error = ((diff == 0) ? CX_OK : CX_INVALID_PARAMETER_VALUE); +cx_err_t cx_aes_gcm_encrypt_and_tag(cx_aes_gcm_context_t *ctx, + uint8_t *in, + size_t len, + const uint8_t *iv, + size_t iv_len, + const uint8_t *aad, + size_t aad_len, + uint8_t *out, + uint8_t *tag, + size_t tag_len) +{ + return cx_aes_gcm_process_and_tag( + ctx, CX_ENCRYPT, in, len, iv, iv_len, aad, aad_len, out, tag, tag_len); +} - // The output buffer is set to 0 if the tag verification fails. - if (error) { - memset(out, 0, len); - } +cx_err_t cx_aes_gcm_decrypt_and_auth(cx_aes_gcm_context_t *ctx, + uint8_t *in, + size_t len, + const uint8_t *iv, + size_t iv_len, + const uint8_t *aad, + size_t aad_len, + uint8_t *out, + const uint8_t *tag, + size_t tag_len) +{ + cx_err_t error; + uint8_t check_tag[AES_BLOCK_BYTES]; + uint8_t diff; + + CX_CHECK(cx_aes_gcm_process_and_tag( + ctx, CX_DECRYPT, in, len, iv, iv_len, aad, aad_len, out, check_tag, tag_len)); + diff = cx_constant_time_eq(tag, check_tag, tag_len); + error = ((diff == 0) ? CX_OK : CX_INVALID_PARAMETER_VALUE); + + // The output buffer is set to 0 if the tag verification fails. + if (error) { + memset(out, 0, len); + } - end: +end: return error; } -cx_err_t cx_aes_gcm_check_tag(cx_aes_gcm_context_t *ctx, const uint8_t *tag, size_t tag_len) { - cx_err_t error; - uint8_t diff; - uint8_t check_tag[AES_GCM_TAG_LEN]; +cx_err_t cx_aes_gcm_check_tag(cx_aes_gcm_context_t *ctx, const uint8_t *tag, size_t tag_len) +{ + cx_err_t error; + uint8_t diff; + uint8_t check_tag[AES_GCM_TAG_LEN]; - if (tag_len > AES_GCM_TAG_LEN) { - return CX_INVALID_PARAMETER_SIZE; - } - CX_CHECK(cx_aes_gcm_finish(ctx, check_tag, tag_len)); + if (tag_len > AES_GCM_TAG_LEN) { + return CX_INVALID_PARAMETER_SIZE; + } + CX_CHECK(cx_aes_gcm_finish(ctx, check_tag, tag_len)); - diff = cx_constant_time_eq(tag, check_tag, tag_len); - error = diff * CX_INVALID_PARAMETER_VALUE + (1 - diff) * CX_OK; - end: + diff = cx_constant_time_eq(tag, check_tag, tag_len); + error = diff * CX_INVALID_PARAMETER_VALUE + (1 - diff) * CX_OK; +end: return error; } -#endif // HAVE_AES_GCM && AES +#endif // HAVE_AES_GCM && AES diff --git a/lib_cxng/src/cx_aes_gcm.h b/lib_cxng/src/cx_aes_gcm.h index 32d3ef8cd..43746c5b3 100644 --- a/lib_cxng/src/cx_aes_gcm.h +++ b/lib_cxng/src/cx_aes_gcm.h @@ -1,51 +1,51 @@ /******************************************************************************* -* Ledger Nano S - Secure firmware -* (c) 2022 Ledger -* -* Licensed under the Apache License, Version 2.0 (the "License"); -* you may not use this file except in compliance with the License. -* You may obtain a copy of the License at -* -* http://www.apache.org/licenses/LICENSE-2.0 -* -* Unless required by applicable law or agreed to in writing, software -* distributed under the License is distributed on an "AS IS" BASIS, -* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -* See the License for the specific language governing permissions and -* limitations under the License. -********************************************************************************/ + * Ledger Nano S - Secure firmware + * (c) 2022 Ledger + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT 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 CX_AES_GCM_H #define CX_AES_GCM_H #if defined(HAVE_AEAD) #include "lcx_aead.h" -#endif // HAVE_AEAD +#endif // HAVE_AEAD #include - // Store unaligned 32-bit integer (big-endian encoding) - #define STORE32BE(a, p) \ - ((uint8_t *)(p))[0] = ((uint32_t)(a) >> 24) & 0xFFU, \ - ((uint8_t *)(p))[1] = ((uint32_t)(a) >> 16) & 0xFFU, \ - ((uint8_t *)(p))[2] = ((uint32_t)(a) >> 8) & 0xFFU, \ - ((uint8_t *)(p))[3] = ((uint32_t)(a) >> 0) & 0xFFU +// Store unaligned 32-bit integer (big-endian encoding) +#define STORE32BE(a, p) \ + ((uint8_t *) (p))[0] = ((uint32_t) (a) >> 24) & 0xFFU, \ + ((uint8_t *) (p))[1] = ((uint32_t) (a) >> 16) & 0xFFU, \ + ((uint8_t *) (p))[2] = ((uint32_t) (a) >> 8) & 0xFFU, \ + ((uint8_t *) (p))[3] = ((uint32_t) (a) >> 0) & 0xFFU - // Store unaligned 64-bit integer (big-endian encoding) - #define STORE64BE(a, p) \ - ((uint8_t *)(p))[0] = ((uint64_t)(a) >> 56) & 0xFFU, \ - ((uint8_t *)(p))[1] = ((uint64_t)(a) >> 48) & 0xFFU, \ - ((uint8_t *)(p))[2] = ((uint64_t)(a) >> 40) & 0xFFU, \ - ((uint8_t *)(p))[3] = ((uint64_t)(a) >> 32) & 0xFFU, \ - ((uint8_t *)(p))[4] = ((uint64_t)(a) >> 24) & 0xFFU, \ - ((uint8_t *)(p))[5] = ((uint64_t)(a) >> 16) & 0xFFU, \ - ((uint8_t *)(p))[6] = ((uint64_t)(a) >> 8) & 0xFFU, \ - ((uint8_t *)(p))[7] = ((uint64_t)(a) >> 0) & 0xFFU +// Store unaligned 64-bit integer (big-endian encoding) +#define STORE64BE(a, p) \ + ((uint8_t *) (p))[0] = ((uint64_t) (a) >> 56) & 0xFFU, \ + ((uint8_t *) (p))[1] = ((uint64_t) (a) >> 48) & 0xFFU, \ + ((uint8_t *) (p))[2] = ((uint64_t) (a) >> 40) & 0xFFU, \ + ((uint8_t *) (p))[3] = ((uint64_t) (a) >> 32) & 0xFFU, \ + ((uint8_t *) (p))[4] = ((uint64_t) (a) >> 24) & 0xFFU, \ + ((uint8_t *) (p))[5] = ((uint64_t) (a) >> 16) & 0xFFU, \ + ((uint8_t *) (p))[6] = ((uint64_t) (a) >> 8) & 0xFFU, \ + ((uint8_t *) (p))[7] = ((uint64_t) (a) >> 0) & 0xFFU #if defined(HAVE_AEAD) extern const cx_aead_info_t cx_aes128_gcm_info; extern const cx_aead_info_t cx_aes192_gcm_info; extern const cx_aead_info_t cx_aes256_gcm_info; -#endif // HAVE_AEAD +#endif // HAVE_AEAD -#endif // CX_AES_GCM_H +#endif // CX_AES_GCM_H diff --git a/lib_cxng/src/cx_aes_siv.c b/lib_cxng/src/cx_aes_siv.c index 987540f35..71fe6fdd8 100644 --- a/lib_cxng/src/cx_aes_siv.c +++ b/lib_cxng/src/cx_aes_siv.c @@ -7,171 +7,177 @@ #include "lcx_cmac.h" #include "lcx_aes_siv.h" -static void cx_clear_bits(uint8_t *input) { - input[8] &= 0x7f; - input[12] &= 0x7f; +static void cx_clear_bits(uint8_t *input) +{ + input[8] &= 0x7f; + input[12] &= 0x7f; } -cx_err_t cx_aes_siv_init(cx_aes_siv_context_t *ctx) { - cx_err_t error; - CX_CHECK(cx_cipher_init(ctx->cipher_ctx)); +cx_err_t cx_aes_siv_init(cx_aes_siv_context_t *ctx) +{ + cx_err_t error; + CX_CHECK(cx_cipher_init(ctx->cipher_ctx)); - end: +end: return error; } -cx_err_t cx_aes_siv_set_key(cx_aes_siv_context_t *ctx, - const uint8_t *key, size_t key_bitlen) { +cx_err_t cx_aes_siv_set_key(cx_aes_siv_context_t *ctx, const uint8_t *key, size_t key_bitlen) +{ + // AES SIV uses two keys of either 128, 192 or 256 bits each + if (key_bitlen > AES_SIV_MAX_KEY_LEN * AES_SIV_KEY_NUMBER * 8) { + return CX_INVALID_PARAMETER_SIZE; + } - // AES SIV uses two keys of either 128, 192 or 256 bits each - if (key_bitlen > AES_SIV_MAX_KEY_LEN * AES_SIV_KEY_NUMBER * 8) { - return CX_INVALID_PARAMETER_SIZE; - } - - ctx->key_len = key_bitlen/2; - memcpy(ctx->key1, key, ctx->key_len/8); - memcpy(ctx->key2, key + ctx->key_len/8, ctx->key_len/8); - return CX_OK; + ctx->key_len = key_bitlen / 2; + memcpy(ctx->key1, key, ctx->key_len / 8); + memcpy(ctx->key2, key + ctx->key_len / 8, ctx->key_len / 8); + return CX_OK; } cx_err_t cx_aes_siv_start(cx_aes_siv_context_t *ctx, - uint32_t mode, - const uint8_t *iv, - size_t iv_len) { - uint8_t iv_used[CX_AES_BLOCK_SIZE] = {0}; - cx_err_t error; - - // Set up cipher to be used for CMAC computation - CX_CHECK(cx_cipher_setup(ctx->cipher_ctx, ctx->cipher_type, CX_CHAIN_ECB)); - CX_CHECK(cx_cmac_start(ctx->cipher_ctx, ctx->key1, ctx->key_len)); - CX_CHECK(cx_cmac_update(ctx->cipher_ctx, iv_used, CX_AES_BLOCK_SIZE)); - CX_CHECK(cx_cmac_finish(ctx->cipher_ctx, ctx->tag_state)); - - if (CX_DECRYPT == mode) { - // Prepare for the AES-CTR computation - memcpy(iv_used, iv, iv_len); - cx_clear_bits(iv_used); - CX_CHECK(cx_cipher_setup(ctx->cipher_ctx, ctx->cipher_type, CX_CHAIN_CTR)); - CX_CHECK(cx_cipher_setkey(ctx->cipher_ctx, ctx->key2, ctx->key_len, CX_ENCRYPT)); - CX_CHECK(cx_cipher_setiv(ctx->cipher_ctx, iv_used, CX_AES_BLOCK_SIZE)); - } - ctx->mode = mode; + uint32_t mode, + const uint8_t *iv, + size_t iv_len) +{ + uint8_t iv_used[CX_AES_BLOCK_SIZE] = {0}; + cx_err_t error; + + // Set up cipher to be used for CMAC computation + CX_CHECK(cx_cipher_setup(ctx->cipher_ctx, ctx->cipher_type, CX_CHAIN_ECB)); + CX_CHECK(cx_cmac_start(ctx->cipher_ctx, ctx->key1, ctx->key_len)); + CX_CHECK(cx_cmac_update(ctx->cipher_ctx, iv_used, CX_AES_BLOCK_SIZE)); + CX_CHECK(cx_cmac_finish(ctx->cipher_ctx, ctx->tag_state)); - end: + if (CX_DECRYPT == mode) { + // Prepare for the AES-CTR computation + memcpy(iv_used, iv, iv_len); + cx_clear_bits(iv_used); + CX_CHECK(cx_cipher_setup(ctx->cipher_ctx, ctx->cipher_type, CX_CHAIN_CTR)); + CX_CHECK(cx_cipher_setkey(ctx->cipher_ctx, ctx->key2, ctx->key_len, CX_ENCRYPT)); + CX_CHECK(cx_cipher_setiv(ctx->cipher_ctx, iv_used, CX_AES_BLOCK_SIZE)); + } + ctx->mode = mode; + +end: return error; } -cx_err_t cx_aes_siv_update_aad(cx_aes_siv_context_t *ctx, - const uint8_t *aad, - size_t aad_len) { - uint8_t tmp[CX_AES_BLOCK_SIZE] = {0}; - cx_err_t error; +cx_err_t cx_aes_siv_update_aad(cx_aes_siv_context_t *ctx, const uint8_t *aad, size_t aad_len) +{ + uint8_t tmp[CX_AES_BLOCK_SIZE] = {0}; + cx_err_t error; - if (NULL == aad) { - return CX_OK; - } + if (NULL == aad) { + return CX_OK; + } - CX_CHECK(cx_cipher_setup(ctx->cipher_ctx, ctx->cipher_type, CX_CHAIN_ECB)); - CX_CHECK(cx_cmac_shift_and_xor(tmp, ctx->tag_state, CX_AES_BLOCK_SIZE)); - CX_CHECK(cx_cmac_start(ctx->cipher_ctx, ctx->key1, ctx->key_len)); - CX_CHECK(cx_cmac_update(ctx->cipher_ctx, aad, aad_len)); - CX_CHECK(cx_cmac_finish(ctx->cipher_ctx, ctx->tag_state)); - cx_memxor(ctx->tag_state, tmp, CX_AES_BLOCK_SIZE); + CX_CHECK(cx_cipher_setup(ctx->cipher_ctx, ctx->cipher_type, CX_CHAIN_ECB)); + CX_CHECK(cx_cmac_shift_and_xor(tmp, ctx->tag_state, CX_AES_BLOCK_SIZE)); + CX_CHECK(cx_cmac_start(ctx->cipher_ctx, ctx->key1, ctx->key_len)); + CX_CHECK(cx_cmac_update(ctx->cipher_ctx, aad, aad_len)); + CX_CHECK(cx_cmac_finish(ctx->cipher_ctx, ctx->tag_state)); + cx_memxor(ctx->tag_state, tmp, CX_AES_BLOCK_SIZE); - end: +end: return error; } cx_err_t cx_aes_siv_update(cx_aes_siv_context_t *ctx, - const uint8_t *input, - uint8_t *output, size_t len) { - size_t out_len = len; - cx_err_t error; - CX_CHECK(cx_cipher_update(ctx->cipher_ctx, input, len, output, &out_len)); - cx_cipher_reset(ctx->cipher_ctx); - - end: + const uint8_t *input, + uint8_t *output, + size_t len) +{ + size_t out_len = len; + cx_err_t error; + CX_CHECK(cx_cipher_update(ctx->cipher_ctx, input, len, output, &out_len)); + cx_cipher_reset(ctx->cipher_ctx); + +end: return error; } -static cx_err_t cx_aes_siv_check_tag(cx_aes_siv_context_t *ctx, - const uint8_t *tag) { - uint8_t diff; - diff = cx_constant_time_eq(tag, ctx->tag_state, CX_AES_BLOCK_SIZE); - return diff * CX_INVALID_PARAMETER_VALUE + (1 - diff) * CX_OK; +static cx_err_t cx_aes_siv_check_tag(cx_aes_siv_context_t *ctx, const uint8_t *tag) +{ + uint8_t diff; + diff = cx_constant_time_eq(tag, ctx->tag_state, CX_AES_BLOCK_SIZE); + return diff * CX_INVALID_PARAMETER_VALUE + (1 - diff) * CX_OK; } cx_err_t cx_aes_siv_finish(cx_aes_siv_context_t *ctx, - const uint8_t *input, size_t in_len, - uint8_t *tag) { - uint8_t tmp[CX_AES_BLOCK_SIZE] = {0}; - cx_err_t error; + const uint8_t *input, + size_t in_len, + uint8_t *tag) +{ + uint8_t tmp[CX_AES_BLOCK_SIZE] = {0}; + cx_err_t error; + + CX_CHECK(cx_cipher_setup(ctx->cipher_ctx, ctx->cipher_type, CX_CHAIN_ECB)); + if (in_len < CX_AES_BLOCK_SIZE) { + CX_CHECK(cx_cmac_shift_and_xor(tmp, ctx->tag_state, CX_AES_BLOCK_SIZE)); + memset(ctx->tag_state, 0, CX_AES_BLOCK_SIZE); + memcpy(ctx->tag_state, input, in_len); + add_one_and_zeros_padding(ctx->tag_state, CX_AES_BLOCK_SIZE, in_len); + cx_memxor(tmp, ctx->tag_state, CX_AES_BLOCK_SIZE); + CX_CHECK(cx_cmac_start(ctx->cipher_ctx, ctx->key1, ctx->key_len)); + CX_CHECK(cx_cmac_update(ctx->cipher_ctx, tmp, CX_AES_BLOCK_SIZE)); + CX_CHECK(cx_cmac_finish(ctx->cipher_ctx, ctx->tag_state)); + } + else { + CX_CHECK(cx_cmac_start(ctx->cipher_ctx, ctx->key1, ctx->key_len)); + CX_CHECK(cx_cmac_update(ctx->cipher_ctx, input, in_len - CX_AES_BLOCK_SIZE)); + cx_memxor(ctx->tag_state, input + in_len - CX_AES_BLOCK_SIZE, CX_AES_BLOCK_SIZE); + CX_CHECK(cx_cmac_update(ctx->cipher_ctx, ctx->tag_state, CX_AES_BLOCK_SIZE)); + CX_CHECK(cx_cmac_finish(ctx->cipher_ctx, ctx->tag_state)); + } + if (CX_DECRYPT == ctx->mode) { + return cx_aes_siv_check_tag(ctx, tag); + } + memcpy(tag, ctx->tag_state, CX_AES_BLOCK_SIZE); + // Prepare for the AES-CTR computation + cx_clear_bits(ctx->tag_state); + CX_CHECK(cx_cipher_setup(ctx->cipher_ctx, ctx->cipher_type, CX_CHAIN_CTR)); + CX_CHECK(cx_cipher_setkey(ctx->cipher_ctx, ctx->key2, ctx->key_len, CX_ENCRYPT)); + CX_CHECK(cx_cipher_setiv(ctx->cipher_ctx, ctx->tag_state, CX_AES_BLOCK_SIZE)); - CX_CHECK(cx_cipher_setup(ctx->cipher_ctx, ctx->cipher_type, CX_CHAIN_ECB)); - if (in_len < CX_AES_BLOCK_SIZE) { - CX_CHECK(cx_cmac_shift_and_xor(tmp, ctx->tag_state, CX_AES_BLOCK_SIZE)); - memset(ctx->tag_state, 0, CX_AES_BLOCK_SIZE); - memcpy(ctx->tag_state, input, in_len); - add_one_and_zeros_padding(ctx->tag_state, CX_AES_BLOCK_SIZE, in_len); - cx_memxor(tmp, ctx->tag_state, CX_AES_BLOCK_SIZE); - CX_CHECK(cx_cmac_start(ctx->cipher_ctx, ctx->key1, ctx->key_len)); - CX_CHECK(cx_cmac_update(ctx->cipher_ctx, tmp, CX_AES_BLOCK_SIZE)); - CX_CHECK(cx_cmac_finish(ctx->cipher_ctx, ctx->tag_state)); - } - else { - CX_CHECK(cx_cmac_start(ctx->cipher_ctx, ctx->key1, ctx->key_len)); - CX_CHECK(cx_cmac_update(ctx->cipher_ctx, input, in_len - CX_AES_BLOCK_SIZE)); - cx_memxor(ctx->tag_state, input + in_len - CX_AES_BLOCK_SIZE, CX_AES_BLOCK_SIZE); - CX_CHECK(cx_cmac_update(ctx->cipher_ctx, ctx->tag_state, CX_AES_BLOCK_SIZE)); - CX_CHECK(cx_cmac_finish(ctx->cipher_ctx, ctx->tag_state)); - } - if (CX_DECRYPT == ctx->mode) { - return cx_aes_siv_check_tag(ctx, tag); - } - memcpy(tag, ctx->tag_state, CX_AES_BLOCK_SIZE); - // Prepare for the AES-CTR computation - cx_clear_bits(ctx->tag_state); - CX_CHECK(cx_cipher_setup(ctx->cipher_ctx, ctx->cipher_type, CX_CHAIN_CTR)); - CX_CHECK(cx_cipher_setkey(ctx->cipher_ctx, ctx->key2, ctx->key_len, CX_ENCRYPT)); - CX_CHECK(cx_cipher_setiv(ctx->cipher_ctx, ctx->tag_state, CX_AES_BLOCK_SIZE)); - - end: +end: return error; - } cx_err_t cx_aes_siv_encrypt(cx_aes_siv_context_t *ctx, - const uint8_t *input, - size_t in_len, - const uint8_t *aad, - size_t aad_len, - uint8_t *output, - uint8_t *tag) { - cx_err_t error; - CX_CHECK(cx_aes_siv_start(ctx, CX_ENCRYPT, NULL, 0)); - CX_CHECK(cx_aes_siv_update_aad(ctx, aad, aad_len)); - CX_CHECK(cx_aes_siv_finish(ctx, input, in_len, tag)); - CX_CHECK(cx_aes_siv_update(ctx, input, output, in_len)); - end: + const uint8_t *input, + size_t in_len, + const uint8_t *aad, + size_t aad_len, + uint8_t *output, + uint8_t *tag) +{ + cx_err_t error; + CX_CHECK(cx_aes_siv_start(ctx, CX_ENCRYPT, NULL, 0)); + CX_CHECK(cx_aes_siv_update_aad(ctx, aad, aad_len)); + CX_CHECK(cx_aes_siv_finish(ctx, input, in_len, tag)); + CX_CHECK(cx_aes_siv_update(ctx, input, output, in_len)); +end: return error; } cx_err_t cx_aes_siv_decrypt(cx_aes_siv_context_t *ctx, - const uint8_t *input, - size_t in_len, - const uint8_t *aad, - size_t aad_len, - uint8_t *output, - uint8_t *tag) { - cx_err_t error; - CX_CHECK(cx_aes_siv_start(ctx, CX_DECRYPT, tag, CX_AES_BLOCK_SIZE)); - CX_CHECK(cx_aes_siv_update(ctx, input, output, in_len)); - CX_CHECK(cx_aes_siv_update_aad(ctx, aad, aad_len)); - CX_CHECK(cx_aes_siv_finish(ctx, output, in_len, tag)); - - end: + const uint8_t *input, + size_t in_len, + const uint8_t *aad, + size_t aad_len, + uint8_t *output, + uint8_t *tag) +{ + cx_err_t error; + CX_CHECK(cx_aes_siv_start(ctx, CX_DECRYPT, tag, CX_AES_BLOCK_SIZE)); + CX_CHECK(cx_aes_siv_update(ctx, input, output, in_len)); + CX_CHECK(cx_aes_siv_update_aad(ctx, aad, aad_len)); + CX_CHECK(cx_aes_siv_finish(ctx, output, in_len, tag)); + +end: return error; } -#endif // HAVE_AES && HAVE_CMAC -#endif // HAVE_AES_SIV +#endif // HAVE_AES && HAVE_CMAC +#endif // HAVE_AES_SIV diff --git a/lib_cxng/src/cx_blake2.h b/lib_cxng/src/cx_blake2.h index bac68542b..d5e957418 100644 --- a/lib_cxng/src/cx_blake2.h +++ b/lib_cxng/src/cx_blake2.h @@ -31,11 +31,11 @@ extern "C" { #endif enum blake2s_constant { - BLAKE2S_BLOCKBYTES = 64, - BLAKE2S_OUTBYTES = 32, - BLAKE2S_KEYBYTES = 32, - BLAKE2S_SALTBYTES = 8, - BLAKE2S_PERSONALBYTES = 8 + BLAKE2S_BLOCKBYTES = 64, + BLAKE2S_OUTBYTES = 32, + BLAKE2S_KEYBYTES = 32, + BLAKE2S_SALTBYTES = 8, + BLAKE2S_PERSONALBYTES = 8 }; /* move to cx.h */ @@ -49,13 +49,13 @@ enum blake2s_constant { }; */ typedef struct blake2s_state__ { - uint32_t h[8]; - uint32_t t[2]; - uint32_t f[2]; - uint8_t buf[BLAKE2S_BLOCKBYTES]; - size_t buflen; - size_t outlen; - uint8_t last_node; + uint32_t h[8]; + uint32_t t[2]; + uint32_t f[2]; + uint8_t buf[BLAKE2S_BLOCKBYTES]; + size_t buflen; + size_t outlen; + uint8_t last_node; } blake2s_state; /* move to cx.h */ @@ -72,69 +72,69 @@ typedef struct blake2b_state__ } blake2b_state; */ typedef struct blake2sp_state__ { - blake2s_state S[8][1]; - blake2s_state R[1]; - uint8_t buf[8 * BLAKE2S_BLOCKBYTES]; - size_t buflen; - size_t outlen; + blake2s_state S[8][1]; + blake2s_state R[1]; + uint8_t buf[8 * BLAKE2S_BLOCKBYTES]; + size_t buflen; + size_t outlen; } blake2sp_state; typedef struct blake2bp_state__ { - blake2b_state S[4][1]; - blake2b_state R[1]; - uint8_t buf[4 * BLAKE2B_BLOCKBYTES]; - size_t buflen; - size_t outlen; + blake2b_state S[4][1]; + blake2b_state R[1]; + uint8_t buf[4 * BLAKE2B_BLOCKBYTES]; + size_t buflen; + size_t outlen; } blake2bp_state; BLAKE2_PACKED(struct blake2s_param__ { - uint8_t digest_length; /* 1 */ - uint8_t key_length; /* 2 */ - uint8_t fanout; /* 3 */ - uint8_t depth; /* 4 */ - uint32_t leaf_length; /* 8 */ - uint32_t node_offset; /* 12 */ - uint16_t xof_length; /* 14 */ - uint8_t node_depth; /* 15 */ - uint8_t inner_length; /* 16 */ - /* uint8_t reserved[0]; */ - uint8_t salt[BLAKE2S_SALTBYTES]; /* 24 */ - uint8_t personal[BLAKE2S_PERSONALBYTES]; /* 32 */ + uint8_t digest_length; /* 1 */ + uint8_t key_length; /* 2 */ + uint8_t fanout; /* 3 */ + uint8_t depth; /* 4 */ + uint32_t leaf_length; /* 8 */ + uint32_t node_offset; /* 12 */ + uint16_t xof_length; /* 14 */ + uint8_t node_depth; /* 15 */ + uint8_t inner_length; /* 16 */ + /* uint8_t reserved[0]; */ + uint8_t salt[BLAKE2S_SALTBYTES]; /* 24 */ + uint8_t personal[BLAKE2S_PERSONALBYTES]; /* 32 */ }); typedef struct blake2s_param__ blake2s_param; BLAKE2_PACKED(struct blake2b_param__ { - uint8_t digest_length; /* 1 */ - uint8_t key_length; /* 2 */ - uint8_t fanout; /* 3 */ - uint8_t depth; /* 4 */ - uint32_t leaf_length; /* 8 */ - uint32_t node_offset; /* 12 */ - uint32_t xof_length; /* 16 */ - uint8_t node_depth; /* 17 */ - uint8_t inner_length; /* 18 */ - uint8_t reserved[14]; /* 32 */ - uint8_t salt[BLAKE2B_SALTBYTES]; /* 48 */ - uint8_t personal[BLAKE2B_PERSONALBYTES]; /* 64 */ + uint8_t digest_length; /* 1 */ + uint8_t key_length; /* 2 */ + uint8_t fanout; /* 3 */ + uint8_t depth; /* 4 */ + uint32_t leaf_length; /* 8 */ + uint32_t node_offset; /* 12 */ + uint32_t xof_length; /* 16 */ + uint8_t node_depth; /* 17 */ + uint8_t inner_length; /* 18 */ + uint8_t reserved[14]; /* 32 */ + uint8_t salt[BLAKE2B_SALTBYTES]; /* 48 */ + uint8_t personal[BLAKE2B_PERSONALBYTES]; /* 64 */ }); typedef struct blake2b_param__ blake2b_param; typedef struct blake2xs_state__ { - blake2s_state S[1]; - blake2s_param P[1]; + blake2s_state S[1]; + blake2s_param P[1]; } blake2xs_state; typedef struct blake2xb_state__ { - blake2b_state S[1]; - blake2b_param P[1]; + blake2b_state S[1]; + blake2b_param P[1]; } blake2xb_state; /* Padded structs result in a compile-time error */ enum { - BLAKE2_DUMMY_1 = 1 / (sizeof(blake2s_param) == BLAKE2S_OUTBYTES), - BLAKE2_DUMMY_2 = 1 / (sizeof(blake2b_param) == BLAKE2B_OUTBYTES) + BLAKE2_DUMMY_1 = 1 / (sizeof(blake2s_param) == BLAKE2S_OUTBYTES), + BLAKE2_DUMMY_2 = 1 / (sizeof(blake2b_param) == BLAKE2B_OUTBYTES) }; /* Streaming API */ @@ -144,16 +144,16 @@ int blake2s_init_param(blake2s_state *S, const blake2s_param *P); int blake2s_update(blake2s_state *S, const void *in, size_t inlen); int blake2s_final(blake2s_state *S, void *out, size_t outlen); -int blake2b_init(blake2b_state *S, - size_t outlen, - unsigned char *salt, - size_t salt_len, - unsigned char *personal, - size_t personal_len); -int blake2b_init_key(blake2b_state *S, size_t outlen, const void *key, size_t keylen); -int blake2b_init_param(blake2b_state *S, const blake2b_param *P); +int blake2b_init(blake2b_state *S, + size_t outlen, + unsigned char *salt, + size_t salt_len, + unsigned char *personal, + size_t personal_len); +int blake2b_init_key(blake2b_state *S, size_t outlen, const void *key, size_t keylen); +int blake2b_init_param(blake2b_state *S, const blake2b_param *P); void blake2b_update(blake2b_state *S, const void *in, size_t inlen); -int blake2b_final(blake2b_state *S, void *out, size_t outlen); +int blake2b_final(blake2b_state *S, void *out, size_t outlen); int blake2sp_init(blake2sp_state *S, size_t outlen); int blake2sp_init_key(blake2sp_state *S, size_t outlen, const void *key, size_t keylen); @@ -180,11 +180,31 @@ int blake2xb_final(blake2xb_state *S, void *out, size_t outlen); int blake2s(void *out, size_t outlen, const void *in, size_t inlen, const void *key, size_t keylen); int blake2b(void *out, size_t outlen, const void *in, size_t inlen, const void *key, size_t keylen); -int blake2sp(void *out, size_t outlen, const void *in, size_t inlen, const void *key, size_t keylen); -int blake2bp(void *out, size_t outlen, const void *in, size_t inlen, const void *key, size_t keylen); - -int blake2xs(void *out, size_t outlen, const void *in, size_t inlen, const void *key, size_t keylen); -int blake2xb(void *out, size_t outlen, const void *in, size_t inlen, const void *key, size_t keylen); +int blake2sp(void *out, + size_t outlen, + const void *in, + size_t inlen, + const void *key, + size_t keylen); +int blake2bp(void *out, + size_t outlen, + const void *in, + size_t inlen, + const void *key, + size_t keylen); + +int blake2xs(void *out, + size_t outlen, + const void *in, + size_t inlen, + const void *key, + size_t keylen); +int blake2xb(void *out, + size_t outlen, + const void *in, + size_t inlen, + const void *key, + size_t keylen); /* This is simply an alias for blake2b */ int blake2(void *out, size_t outlen, const void *in, size_t inlen, const void *key, size_t keylen); @@ -195,4 +215,4 @@ int blake2(void *out, size_t outlen, const void *in, size_t inlen, const void *k #endif -#endif // HAVE_BLAKE2 +#endif // HAVE_BLAKE2 diff --git a/lib_cxng/src/cx_blake2b.c b/lib_cxng/src/cx_blake2b.c index af7695173..426069b6d 100644 --- a/lib_cxng/src/cx_blake2b.c +++ b/lib_cxng/src/cx_blake2b.c @@ -1,21 +1,21 @@ /******************************************************************************* -* Ledger Nano S - Secure firmware -* (c) 2022 Ledger -* -* Licensed under the Apache License, Version 2.0 (the "License"); -* you may not use this file except in compliance with the License. -* You may obtain a copy of the License at -* -* http://www.apache.org/licenses/LICENSE-2.0 -* -* Unless required by applicable law or agreed to in writing, software -* distributed under the License is distributed on an "AS IS" BASIS, -* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -* See the License for the specific language governing permissions and -* limitations under the License. -********************************************************************************/ + * Ledger Nano S - Secure firmware + * (c) 2022 Ledger + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + ********************************************************************************/ #ifdef HAVE_BLAKE2 @@ -31,88 +31,98 @@ #endif #endif -const cx_hash_info_t cx_blake2b_info = { - CX_BLAKE2B, - 0, - BLAKE2B_BLOCKBYTES, - sizeof(cx_blake2b_t), - NULL, - (cx_err_t (*)(cx_hash_t *ctx, const uint8_t *data, size_t len))cx_blake2b_update, - (cx_err_t (*)(cx_hash_t *ctx, uint8_t *digest))cx_blake2b_final, - (cx_err_t(*)(cx_hash_t *ctx, size_t output_size))cx_blake2b_init_no_throw, - (size_t(*)(const cx_hash_t *ctx))cx_blake2b_get_output_size -}; - -cx_err_t cx_blake2b_init_no_throw(cx_blake2b_t *hash, size_t size) { - return cx_blake2b_init2_no_throw(hash, size, NULL, 0, NULL, 0); +const cx_hash_info_t cx_blake2b_info + = {CX_BLAKE2B, + 0, + BLAKE2B_BLOCKBYTES, + sizeof(cx_blake2b_t), + NULL, + (cx_err_t(*)(cx_hash_t * ctx, const uint8_t *data, size_t len)) cx_blake2b_update, + (cx_err_t(*)(cx_hash_t * ctx, uint8_t *digest)) cx_blake2b_final, + (cx_err_t(*)(cx_hash_t * ctx, size_t output_size)) cx_blake2b_init_no_throw, + (size_t(*)(const cx_hash_t *ctx)) cx_blake2b_get_output_size}; + +cx_err_t cx_blake2b_init_no_throw(cx_blake2b_t *hash, size_t size) +{ + return cx_blake2b_init2_no_throw(hash, size, NULL, 0, NULL, 0); } cx_err_t cx_blake2b_init2_no_throw(cx_blake2b_t *hash, - size_t size, - uint8_t * salt, - size_t salt_len, - uint8_t * perso, - size_t perso_len) { - if (salt == NULL && salt_len != 0) { - goto err; - } - if (perso == NULL && perso_len != 0) { - goto err; - } - if (salt_len > 16 || perso_len > 16) { - goto err; - } - if (size % 8 != 0 || size < 8 || size > 512) { - goto err; - } - memset(hash, 0, sizeof(cx_blake2b_t)); - - size = size / 8; - hash->output_size = size; - hash->header.info = &cx_blake2b_info; - - if (blake2b_init(&hash->ctx, size, salt, salt_len, perso, perso_len) < 0) { - goto err; - } - return CX_OK; + size_t size, + uint8_t *salt, + size_t salt_len, + uint8_t *perso, + size_t perso_len) +{ + if (salt == NULL && salt_len != 0) { + goto err; + } + if (perso == NULL && perso_len != 0) { + goto err; + } + if (salt_len > 16 || perso_len > 16) { + goto err; + } + if (size % 8 != 0 || size < 8 || size > 512) { + goto err; + } + memset(hash, 0, sizeof(cx_blake2b_t)); + + size = size / 8; + hash->output_size = size; + hash->header.info = &cx_blake2b_info; + + if (blake2b_init(&hash->ctx, size, salt, salt_len, perso, perso_len) < 0) { + goto err; + } + return CX_OK; err: - return CX_INVALID_PARAMETER; + return CX_INVALID_PARAMETER; } -cx_err_t cx_blake2b_update(cx_blake2b_t *ctx, const uint8_t *data, size_t len) { - if (ctx == NULL) { - return CX_INVALID_PARAMETER; - } - if (data == NULL && len != 0) { - return CX_INVALID_PARAMETER; - } - blake2b_update(&ctx->ctx, data, len); - return CX_OK; +cx_err_t cx_blake2b_update(cx_blake2b_t *ctx, const uint8_t *data, size_t len) +{ + if (ctx == NULL) { + return CX_INVALID_PARAMETER; + } + if (data == NULL && len != 0) { + return CX_INVALID_PARAMETER; + } + blake2b_update(&ctx->ctx, data, len); + return CX_OK; } -cx_err_t cx_blake2b_final(cx_blake2b_t *ctx, uint8_t *digest) { - (void)blake2b_final(&ctx->ctx, digest, ctx->output_size); - return CX_OK; +cx_err_t cx_blake2b_final(cx_blake2b_t *ctx, uint8_t *digest) +{ + (void) blake2b_final(&ctx->ctx, digest, ctx->output_size); + return CX_OK; } -size_t cx_blake2b_get_output_size(const cx_blake2b_t *ctx) { - return ctx->output_size; +size_t cx_blake2b_get_output_size(const cx_blake2b_t *ctx) +{ + return ctx->output_size; } -cx_err_t cx_blake2b(cx_hash_t *hash, uint32_t mode, const uint8_t *in, size_t len, uint8_t *out, size_t out_len) { - size_t sz = 0; - blake2b_update(&((cx_blake2b_t *)hash)->ctx, in, len); - if (mode & CX_LAST) { - sz = ((cx_blake2b_t *)hash)->output_size; - if (out && (out_len < sz)) { - return INVALID_PARAMETER; +cx_err_t cx_blake2b(cx_hash_t *hash, + uint32_t mode, + const uint8_t *in, + size_t len, + uint8_t *out, + size_t out_len) +{ + size_t sz = 0; + blake2b_update(&((cx_blake2b_t *) hash)->ctx, in, len); + if (mode & CX_LAST) { + sz = ((cx_blake2b_t *) hash)->output_size; + if (out && (out_len < sz)) { + return INVALID_PARAMETER; + } + if ((size_t) blake2b_final(&((cx_blake2b_t *) hash)->ctx, out, out_len) != sz) { + return INVALID_PARAMETER; + } } - if ((size_t)blake2b_final(&((cx_blake2b_t *)hash)->ctx, out, out_len) != sz) { - return INVALID_PARAMETER; - } - } - return CX_OK; + return CX_OK; } /* @@ -130,11 +140,11 @@ cx_err_t cx_blake2b(cx_hash_t *hash, uint32_t mode, const uint8_t *in, size_t le https://blake2.net. */ -//#include -//#include -//#include +// #include +// #include +// #include -//#include "cx_blake2.h" //moved on top +// #include "cx_blake2.h" //moved on top #include #include @@ -157,254 +167,293 @@ cx_err_t cx_blake2b(cx_hash_t *hash, uint32_t mode, const uint8_t *in, size_t le #endif #if defined(BLAKE2_UNUSED) -static BLAKE2_INLINE uint16_t load16(const void *src) { +static BLAKE2_INLINE uint16_t load16(const void *src) +{ #if defined(NATIVE_LITTLE_ENDIAN) - uint16_t w; - memcpy(&w, src, sizeof w); - return w; + uint16_t w; + memcpy(&w, src, sizeof w); + return w; #else - const uint8_t *p = (const uint8_t *)src; - return ((uint16_t)(p[0]) << 0) | ((uint16_t)(p[1]) << 8); + const uint8_t *p = (const uint8_t *) src; + return ((uint16_t) (p[0]) << 0) | ((uint16_t) (p[1]) << 8); #endif } -static BLAKE2_INLINE void store16(void *dst, uint16_t w) { +static BLAKE2_INLINE void store16(void *dst, uint16_t w) +{ #if defined(NATIVE_LITTLE_ENDIAN) - memcpy(dst, &w, sizeof w); + memcpy(dst, &w, sizeof w); #else - uint8_t *p = (uint8_t *)dst; - *p++ = (uint8_t)w; - w >>= 8; - *p++ = (uint8_t)w; + uint8_t *p = (uint8_t *) dst; + *p++ = (uint8_t) w; + w >>= 8; + *p++ = (uint8_t) w; #endif } -static BLAKE2_INLINE uint32_t load32(const void *src) { +static BLAKE2_INLINE uint32_t load32(const void *src) +{ #if defined(NATIVE_LITTLE_ENDIAN) - uint32_t w; - memcpy(&w, src, sizeof w); - return w; + uint32_t w; + memcpy(&w, src, sizeof w); + return w; #else - const uint8_t *p = (const uint8_t *)src; - return ((uint32_t)(p[0]) << 0) | ((uint32_t)(p[1]) << 8) | ((uint32_t)(p[2]) << 16) | ((uint32_t)(p[3]) << 24); + const uint8_t *p = (const uint8_t *) src; + return ((uint32_t) (p[0]) << 0) | ((uint32_t) (p[1]) << 8) | ((uint32_t) (p[2]) << 16) + | ((uint32_t) (p[3]) << 24); #endif } -static BLAKE2_INLINE uint64_t load48(const void *src) { - const uint8_t *p = (const uint8_t *)src; - return ((uint64_t)(p[0]) << 0) | ((uint64_t)(p[1]) << 8) | ((uint64_t)(p[2]) << 16) | ((uint64_t)(p[3]) << 24) | - ((uint64_t)(p[4]) << 32) | ((uint64_t)(p[5]) << 40); +static BLAKE2_INLINE uint64_t load48(const void *src) +{ + const uint8_t *p = (const uint8_t *) src; + return ((uint64_t) (p[0]) << 0) | ((uint64_t) (p[1]) << 8) | ((uint64_t) (p[2]) << 16) + | ((uint64_t) (p[3]) << 24) | ((uint64_t) (p[4]) << 32) | ((uint64_t) (p[5]) << 40); } -static BLAKE2_INLINE void store48(void *dst, uint64_t w) { - uint8_t *p = (uint8_t *)dst; - p[0] = (uint8_t)(w >> 0); - p[1] = (uint8_t)(w >> 8); - p[2] = (uint8_t)(w >> 16); - p[3] = (uint8_t)(w >> 24); - p[4] = (uint8_t)(w >> 32); - p[5] = (uint8_t)(w >> 40); +static BLAKE2_INLINE void store48(void *dst, uint64_t w) +{ + uint8_t *p = (uint8_t *) dst; + p[0] = (uint8_t) (w >> 0); + p[1] = (uint8_t) (w >> 8); + p[2] = (uint8_t) (w >> 16); + p[3] = (uint8_t) (w >> 24); + p[4] = (uint8_t) (w >> 32); + p[5] = (uint8_t) (w >> 40); } #endif -static BLAKE2_INLINE void store32(void *dst, uint32_t w) { +static BLAKE2_INLINE void store32(void *dst, uint32_t w) +{ #if defined(NATIVE_LITTLE_ENDIAN) - memcpy(dst, &w, sizeof w); + memcpy(dst, &w, sizeof w); #else - uint8_t *p = (uint8_t *)dst; - p[0] = (uint8_t)(w >> 0); - p[1] = (uint8_t)(w >> 8); - p[2] = (uint8_t)(w >> 16); - p[3] = (uint8_t)(w >> 24); + uint8_t *p = (uint8_t *) dst; + p[0] = (uint8_t) (w >> 0); + p[1] = (uint8_t) (w >> 8); + p[2] = (uint8_t) (w >> 16); + p[3] = (uint8_t) (w >> 24); #endif } -static BLAKE2_INLINE uint64_t load64(const void *src) { +static BLAKE2_INLINE uint64_t load64(const void *src) +{ #if defined(NATIVE_LITTLE_ENDIAN) - uint64_t w; - memcpy(&w, src, sizeof w); - return w; + uint64_t w; + memcpy(&w, src, sizeof w); + return w; #else - const uint8_t *p = (const uint8_t *)src; - return ((uint64_t)(p[0]) << 0) | ((uint64_t)(p[1]) << 8) | ((uint64_t)(p[2]) << 16) | ((uint64_t)(p[3]) << 24) | - ((uint64_t)(p[4]) << 32) | ((uint64_t)(p[5]) << 40) | ((uint64_t)(p[6]) << 48) | ((uint64_t)(p[7]) << 56); + const uint8_t *p = (const uint8_t *) src; + return ((uint64_t) (p[0]) << 0) | ((uint64_t) (p[1]) << 8) | ((uint64_t) (p[2]) << 16) + | ((uint64_t) (p[3]) << 24) | ((uint64_t) (p[4]) << 32) | ((uint64_t) (p[5]) << 40) + | ((uint64_t) (p[6]) << 48) | ((uint64_t) (p[7]) << 56); #endif } -static BLAKE2_INLINE void store64(void *dst, uint64_t w) { +static BLAKE2_INLINE void store64(void *dst, uint64_t w) +{ #if defined(NATIVE_LITTLE_ENDIAN) - memcpy(dst, &w, sizeof w); + memcpy(dst, &w, sizeof w); #else - uint8_t *p = (uint8_t *)dst; - p[0] = (uint8_t)(w >> 0); - p[1] = (uint8_t)(w >> 8); - p[2] = (uint8_t)(w >> 16); - p[3] = (uint8_t)(w >> 24); - p[4] = (uint8_t)(w >> 32); - p[5] = (uint8_t)(w >> 40); - p[6] = (uint8_t)(w >> 48); - p[7] = (uint8_t)(w >> 56); + uint8_t *p = (uint8_t *) dst; + p[0] = (uint8_t) (w >> 0); + p[1] = (uint8_t) (w >> 8); + p[2] = (uint8_t) (w >> 16); + p[3] = (uint8_t) (w >> 24); + p[4] = (uint8_t) (w >> 32); + p[5] = (uint8_t) (w >> 40); + p[6] = (uint8_t) (w >> 48); + p[7] = (uint8_t) (w >> 56); #endif } - - #if defined(BLAKE2_UNUSED) -static BLAKE2_INLINE uint32_t rotr32(const uint32_t w, const unsigned c) { - return (w >> c) | (w << (32 - c)); +static BLAKE2_INLINE uint32_t rotr32(const uint32_t w, const unsigned c) +{ + return (w >> c) | (w << (32 - c)); } #endif -static BLAKE2_INLINE uint64_t rotr64(const uint64_t w, const unsigned c) { - return (w >> c) | (w << (64 - c)); +static BLAKE2_INLINE uint64_t rotr64(const uint64_t w, const unsigned c) +{ + return (w >> c) | (w << (64 - c)); } /* prevents compiler optimizing out memset() */ -static BLAKE2_INLINE void secure_zero_memory(void *v, size_t n) { - memset(v, 0, n); +static BLAKE2_INLINE void secure_zero_memory(void *v, size_t n) +{ + memset(v, 0, n); } /* endof inline *** */ -static const uint64_t blake2b_IV[8] = {0x6a09e667f3bcc908ULL, 0xbb67ae8584caa73bULL, 0x3c6ef372fe94f82bULL, - 0xa54ff53a5f1d36f1ULL, 0x510e527fade682d1ULL, 0x9b05688c2b3e6c1fULL, - 0x1f83d9abfb41bd6bULL, 0x5be0cd19137e2179ULL}; +static const uint64_t blake2b_IV[8] = {0x6a09e667f3bcc908ULL, + 0xbb67ae8584caa73bULL, + 0x3c6ef372fe94f82bULL, + 0xa54ff53a5f1d36f1ULL, + 0x510e527fade682d1ULL, + 0x9b05688c2b3e6c1fULL, + 0x1f83d9abfb41bd6bULL, + 0x5be0cd19137e2179ULL}; static const uint8_t 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 blake2b_set_lastnode(blake2b_state *S) { - S->f[1] = (uint64_t)-1; + {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 blake2b_set_lastnode(blake2b_state *S) +{ + S->f[1] = (uint64_t) -1; } /* Some helper functions, not necessarily useful */ -static int blake2b_is_lastblock(const blake2b_state *S) { - return S->f[0] != 0; +static int blake2b_is_lastblock(const blake2b_state *S) +{ + return S->f[0] != 0; } -static void blake2b_set_lastblock(blake2b_state *S) { - if (S->last_node) - blake2b_set_lastnode(S); +static void blake2b_set_lastblock(blake2b_state *S) +{ + if (S->last_node) { + blake2b_set_lastnode(S); + } - S->f[0] = (uint64_t)-1; + S->f[0] = (uint64_t) -1; } -static void blake2b_increment_counter(blake2b_state *S, const uint64_t inc) { - S->t[0] += inc; - S->t[1] += (S->t[0] < inc); +static void blake2b_increment_counter(blake2b_state *S, const uint64_t inc) +{ + S->t[0] += inc; + S->t[1] += (S->t[0] < inc); } -static void blake2b_init0(blake2b_state *S) { - size_t i; - memset(S, 0, sizeof(blake2b_state)); +static void blake2b_init0(blake2b_state *S) +{ + size_t i; + memset(S, 0, sizeof(blake2b_state)); - for (i = 0; i < 8; ++i) - S->h[i] = blake2b_IV[i]; + for (i = 0; i < 8; ++i) { + S->h[i] = blake2b_IV[i]; + } } /* init xors IV with input parameter block */ -int blake2b_init_param(blake2b_state *S, const blake2b_param *P) { - const uint8_t *p = (const uint8_t *)(P); - size_t i; +int blake2b_init_param(blake2b_state *S, const blake2b_param *P) +{ + const uint8_t *p = (const uint8_t *) (P); + size_t i; - blake2b_init0(S); + blake2b_init0(S); - /* IV XOR ParamBlock */ - for (i = 0; i < 8; ++i) - S->h[i] ^= load64(p + sizeof(S->h[i]) * i); + /* IV XOR ParamBlock */ + for (i = 0; i < 8; ++i) { + S->h[i] ^= load64(p + sizeof(S->h[i]) * i); + } - S->outlen = P->digest_length; - return 0; + S->outlen = P->digest_length; + return 0; } int blake2b_init(blake2b_state *S, size_t outlen, - uint8_t * salt, + uint8_t *salt, size_t salt_len, - uint8_t * personal, - size_t personal_len) { - blake2b_param P[1]; + uint8_t *personal, + size_t personal_len) +{ + blake2b_param P[1]; - if ((!outlen) || (outlen > BLAKE2B_OUTBYTES)) - return CX_INVALID_PARAMETER; + if ((!outlen) || (outlen > BLAKE2B_OUTBYTES)) { + return CX_INVALID_PARAMETER; + } - P->digest_length = (uint8_t)outlen; - P->key_length = 0; - P->fanout = 1; - P->depth = 1; - store32(&P->leaf_length, 0); - store32(&P->node_offset, 0); - store32(&P->xof_length, 0); - P->node_depth = 0; - P->inner_length = 0; - memset(P->reserved, 0, sizeof(P->reserved)); - memset(P->salt, 0, sizeof(P->salt)); - memset(P->personal, 0, sizeof(P->personal)); - if (salt) { - memcpy(P->salt, salt, salt_len); - } - if (personal) { - memcpy(P->personal, personal, personal_len); - } - return blake2b_init_param(S, P); + P->digest_length = (uint8_t) outlen; + P->key_length = 0; + P->fanout = 1; + P->depth = 1; + store32(&P->leaf_length, 0); + store32(&P->node_offset, 0); + store32(&P->xof_length, 0); + P->node_depth = 0; + P->inner_length = 0; + memset(P->reserved, 0, sizeof(P->reserved)); + memset(P->salt, 0, sizeof(P->salt)); + memset(P->personal, 0, sizeof(P->personal)); + if (salt) { + memcpy(P->salt, salt, salt_len); + } + if (personal) { + memcpy(P->personal, personal, personal_len); + } + return blake2b_init_param(S, P); } -int blake2b_init_key(blake2b_state *S, size_t outlen, const void *key, size_t keylen) { - blake2b_param P[1]; +int blake2b_init_key(blake2b_state *S, size_t outlen, const void *key, size_t keylen) +{ + blake2b_param P[1]; - if ((!outlen) || (outlen > BLAKE2B_OUTBYTES)) - return -1; + if ((!outlen) || (outlen > BLAKE2B_OUTBYTES)) { + return -1; + } - if (!key || !keylen || keylen > BLAKE2B_KEYBYTES) - return -1; + if (!key || !keylen || keylen > BLAKE2B_KEYBYTES) { + return -1; + } - P->digest_length = (uint8_t)outlen; - P->key_length = (uint8_t)keylen; - P->fanout = 1; - P->depth = 1; - store32(&P->leaf_length, 0); - store32(&P->node_offset, 0); - store32(&P->xof_length, 0); - P->node_depth = 0; - P->inner_length = 0; - memset(P->reserved, 0, sizeof(P->reserved)); - memset(P->salt, 0, sizeof(P->salt)); - memset(P->personal, 0, sizeof(P->personal)); - - if (blake2b_init_param(S, P) < 0) - return -1; + P->digest_length = (uint8_t) outlen; + P->key_length = (uint8_t) keylen; + P->fanout = 1; + P->depth = 1; + store32(&P->leaf_length, 0); + store32(&P->node_offset, 0); + store32(&P->xof_length, 0); + P->node_depth = 0; + P->inner_length = 0; + memset(P->reserved, 0, sizeof(P->reserved)); + memset(P->salt, 0, sizeof(P->salt)); + memset(P->personal, 0, sizeof(P->personal)); + + if (blake2b_init_param(S, P) < 0) { + return -1; + } - { + { // uint8_t block[BLAKE2B_BLOCKBYTES]; #define block G_cx.blake.block1 - memset(block, 0, BLAKE2B_BLOCKBYTES); - memcpy(block, key, keylen); - blake2b_update(S, block, BLAKE2B_BLOCKBYTES); - secure_zero_memory(block, BLAKE2B_BLOCKBYTES); /* Burn the key from stack */ + memset(block, 0, BLAKE2B_BLOCKBYTES); + memcpy(block, key, keylen); + blake2b_update(S, block, BLAKE2B_BLOCKBYTES); + secure_zero_memory(block, BLAKE2B_BLOCKBYTES); /* Burn the key from stack */ #undef block - } - return 0; + } + return 0; } -#define G(r, i, a, b, c, d) \ - do { \ - a = a + b + m[blake2b_sigma[r][2 * (i) + 0]]; \ - d = rotr64(d ^ a, 32); \ - c = c + d; \ - b = rotr64(b ^ c, 24); \ - a = a + b + m[blake2b_sigma[r][2 * (i) + 1]]; \ - d = rotr64(d ^ a, 16); \ - c = c + d; \ - b = rotr64(b ^ c, 63); \ - } while (0) - -static void blake2b_compress(blake2b_state *S, const uint8_t block[BLAKE2B_BLOCKBYTES]) { +#define G(r, i, a, b, c, d) \ + do { \ + a = a + b + m[blake2b_sigma[r][2 * (i) + 0]]; \ + d = rotr64(d ^ a, 32); \ + c = c + d; \ + b = rotr64(b ^ c, 24); \ + a = a + b + m[blake2b_sigma[r][2 * (i) + 1]]; \ + d = rotr64(d ^ a, 16); \ + c = c + d; \ + b = rotr64(b ^ c, 63); \ + } while (0) + +static void blake2b_compress(blake2b_state *S, const uint8_t block[BLAKE2B_BLOCKBYTES]) +{ /* uint64_t m[16]; uint64_t v[16]; @@ -412,38 +461,38 @@ uint64_t v[16]; #define m G_cx.blake.m #define v G_cx.blake.v - size_t i; - - for (i = 0; i < 16; ++i) { - m[i] = load64(block + i * sizeof(m[i])); - } + size_t i; - for (i = 0; i < 8; ++i) { - v[i] = S->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] ^ S->t[0]; - v[13] = blake2b_IV[5] ^ S->t[1]; - v[14] = blake2b_IV[6] ^ S->f[0]; - v[15] = blake2b_IV[7] ^ S->f[1]; + for (i = 0; i < 16; ++i) { + m[i] = load64(block + i * sizeof(m[i])); + } - for (int r = 0; r < 12; r++) { - for (i = 0; i < 4; i++) { - G(r, i, v[i], v[4 + i], v[8 + i], v[12 + i]); + for (i = 0; i < 8; ++i) { + v[i] = S->h[i]; } - for (i = 0; i < 4; i++) { - G(r, 4 + i, v[i], v[4 + ((i + 1) & 3)], v[8 + ((i + 2) & 3)], v[12 + ((i + 3) & 3)]); + 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] ^ S->t[0]; + v[13] = blake2b_IV[5] ^ S->t[1]; + v[14] = blake2b_IV[6] ^ S->f[0]; + v[15] = blake2b_IV[7] ^ S->f[1]; + + for (int r = 0; r < 12; r++) { + for (i = 0; i < 4; i++) { + G(r, i, v[i], v[4 + i], v[8 + i], v[12 + i]); + } + + for (i = 0; i < 4; i++) { + G(r, 4 + i, v[i], v[4 + ((i + 1) & 3)], v[8 + ((i + 2) & 3)], v[12 + ((i + 3) & 3)]); + } } - } - for (i = 0; i < 8; ++i) { - S->h[i] = S->h[i] ^ v[i] ^ v[i + 8]; - } + for (i = 0; i < 8; ++i) { + S->h[i] = S->h[i] ^ v[i] ^ v[i + 8]; + } #undef m #undef v } @@ -451,55 +500,60 @@ uint64_t v[16]; #undef G #undef ROUND -void blake2b_update(blake2b_state *S, const void *pin, size_t inlen) { - const uint8_t *in = (const uint8_t *)pin; - if (inlen > 0) { - size_t left = S->buflen; - size_t fill = BLAKE2B_BLOCKBYTES - left; - if (inlen > fill) { - S->buflen = 0; - memcpy(S->buf + left, in, fill); /* Fill buffer */ - blake2b_increment_counter(S, BLAKE2B_BLOCKBYTES); - blake2b_compress(S, S->buf); /* Compress */ - in += fill; - inlen -= fill; - while (inlen > BLAKE2B_BLOCKBYTES) { - blake2b_increment_counter(S, BLAKE2B_BLOCKBYTES); - blake2b_compress(S, in); - in += BLAKE2B_BLOCKBYTES; - inlen -= BLAKE2B_BLOCKBYTES; - } - } - memcpy(S->buf + S->buflen, in, inlen); - S->buflen += inlen; - } +void blake2b_update(blake2b_state *S, const void *pin, size_t inlen) +{ + const uint8_t *in = (const uint8_t *) pin; + if (inlen > 0) { + size_t left = S->buflen; + size_t fill = BLAKE2B_BLOCKBYTES - left; + if (inlen > fill) { + S->buflen = 0; + memcpy(S->buf + left, in, fill); /* Fill buffer */ + blake2b_increment_counter(S, BLAKE2B_BLOCKBYTES); + blake2b_compress(S, S->buf); /* Compress */ + in += fill; + inlen -= fill; + while (inlen > BLAKE2B_BLOCKBYTES) { + blake2b_increment_counter(S, BLAKE2B_BLOCKBYTES); + blake2b_compress(S, in); + in += BLAKE2B_BLOCKBYTES; + inlen -= BLAKE2B_BLOCKBYTES; + } + } + memcpy(S->buf + S->buflen, in, inlen); + S->buflen += inlen; + } } -int blake2b_final(blake2b_state *S, void *out, size_t outlen) { - size_t i; +int blake2b_final(blake2b_state *S, void *out, size_t outlen) +{ + size_t i; // uint8_t buffer[BLAKE2B_OUTBYTES] = {0}; #define buffer G_cx.blake.buffer - memset(buffer, 0, BLAKE2B_OUTBYTES); + memset(buffer, 0, BLAKE2B_OUTBYTES); - if ((out != NULL) && (outlen < S->outlen)) - return -1; + if ((out != NULL) && (outlen < S->outlen)) { + return -1; + } - if (blake2b_is_lastblock(S)) - return -1; + if (blake2b_is_lastblock(S)) { + return -1; + } - blake2b_increment_counter(S, S->buflen); - blake2b_set_lastblock(S); - memset(S->buf + S->buflen, 0, BLAKE2B_BLOCKBYTES - S->buflen); /* Padding */ - blake2b_compress(S, S->buf); - - for (i = 0; i < 8; ++i) /* Output full hash to temp buffer */ - store64(buffer + sizeof(S->h[i]) * i, S->h[i]); - memcpy(S->buf, buffer, S->outlen); //.acc destination - if (out) { - memcpy(out, buffer, S->outlen); - } - secure_zero_memory(buffer, sizeof(buffer)); - return S->outlen; + blake2b_increment_counter(S, S->buflen); + blake2b_set_lastblock(S); + memset(S->buf + S->buflen, 0, BLAKE2B_BLOCKBYTES - S->buflen); /* Padding */ + blake2b_compress(S, S->buf); + + for (i = 0; i < 8; ++i) { /* Output full hash to temp buffer */ + store64(buffer + sizeof(S->h[i]) * i, S->h[i]); + } + memcpy(S->buf, buffer, S->outlen); //.acc destination + if (out) { + memcpy(out, buffer, S->outlen); + } + secure_zero_memory(buffer, sizeof(buffer)); + return S->outlen; #undef buffer } @@ -507,102 +561,115 @@ int blake2b_final(blake2b_state *S, void *out, size_t outlen) { // Following code is not used #if defined(BLAKE2_UNUSED) /* inlen, at least, should be uint64_t. Others can be size_t. */ -int blake2b(void *out, size_t outlen, const void *in, size_t inlen, const void *key, size_t keylen) { - blake2b_state S[1]; +int blake2b(void *out, size_t outlen, const void *in, size_t inlen, const void *key, size_t keylen) +{ + blake2b_state S[1]; - /* Verify parameters */ - if (NULL == in && inlen > 0) - return -1; + /* Verify parameters */ + if (NULL == in && inlen > 0) { + return -1; + } - if (NULL == out) - return -1; + if (NULL == out) { + return -1; + } - if (NULL == key && keylen > 0) - return -1; + if (NULL == key && keylen > 0) { + return -1; + } - if (!outlen || outlen > BLAKE2B_OUTBYTES) - return -1; + if (!outlen || outlen > BLAKE2B_OUTBYTES) { + return -1; + } - if (keylen > BLAKE2B_KEYBYTES) - return -1; + if (keylen > BLAKE2B_KEYBYTES) { + return -1; + } - if (keylen > 0) { - if (blake2b_init_key(S, outlen, key, keylen) < 0) - return -1; - } else { - if (blake2b_init(S, outlen) < 0) - return -1; - } + if (keylen > 0) { + if (blake2b_init_key(S, outlen, key, keylen) < 0) { + return -1; + } + } + else { + if (blake2b_init(S, outlen) < 0) { + return -1; + } + } - blake2b_update(S, (const uint8_t *)in, inlen); - return blake2b_final(S, out, outlen); + blake2b_update(S, (const uint8_t *) in, inlen); + return blake2b_final(S, out, outlen); } -int blake2(void *out, size_t outlen, const void *in, size_t inlen, const void *key, size_t keylen) { - return blake2b(out, outlen, in, inlen, key, keylen); +int blake2(void *out, size_t outlen, const void *in, size_t inlen, const void *key, size_t keylen) +{ + return blake2b(out, outlen, in, inlen, key, keylen); } #if defined(BLAKE2B_SELFTEST) #include #include "blake2-kat.h" -int main(void) { - uint8_t key[BLAKE2B_KEYBYTES]; - uint8_t buf[BLAKE2_KAT_LENGTH]; - size_t i, step; +int main(void) +{ + uint8_t key[BLAKE2B_KEYBYTES]; + uint8_t buf[BLAKE2_KAT_LENGTH]; + size_t i, step; + + for (i = 0; i < BLAKE2B_KEYBYTES; ++i) { + key[i] = (uint8_t) i; + } - for (i = 0; i < BLAKE2B_KEYBYTES; ++i) - key[i] = (uint8_t)i; + for (i = 0; i < BLAKE2_KAT_LENGTH; ++i) { + buf[i] = (uint8_t) i; + } - for (i = 0; i < BLAKE2_KAT_LENGTH; ++i) - buf[i] = (uint8_t)i; + /* Test simple API */ + for (i = 0; i < BLAKE2_KAT_LENGTH; ++i) { + uint8_t hash[BLAKE2B_OUTBYTES]; + blake2b(hash, BLAKE2B_OUTBYTES, buf, i, key, BLAKE2B_KEYBYTES); - /* Test simple API */ - for (i = 0; i < BLAKE2_KAT_LENGTH; ++i) { - uint8_t hash[BLAKE2B_OUTBYTES]; - blake2b(hash, BLAKE2B_OUTBYTES, buf, i, key, BLAKE2B_KEYBYTES); + if (0 != memcmp(hash, blake2b_keyed_kat[i], BLAKE2B_OUTBYTES)) { + goto fail; + } + } - if (0 != memcmp(hash, blake2b_keyed_kat[i], BLAKE2B_OUTBYTES)) { - goto fail; + /* Test streaming API */ + for (step = 1; step < BLAKE2B_BLOCKBYTES; ++step) { + for (i = 0; i < BLAKE2_KAT_LENGTH; ++i) { + uint8_t hash[BLAKE2B_OUTBYTES]; + blake2b_state S; + uint8_t *p = buf; + size_t mlen = i; + int err = 0; + + if ((err = blake2b_init_key(&S, BLAKE2B_OUTBYTES, key, BLAKE2B_KEYBYTES)) < 0) { + goto fail; + } + + while (mlen >= step) { + blake2b_update(&S, p, step); + mlen -= step; + p += step; + } + blake2b_update(&S, p, mlen); + if ((err = blake2b_final(&S, hash, BLAKE2B_OUTBYTES)) < 0) { + goto fail; + } + + if (0 != memcmp(hash, blake2b_keyed_kat[i], BLAKE2B_OUTBYTES)) { + goto fail; + } + } } - } - /* Test streaming API */ - for (step = 1; step < BLAKE2B_BLOCKBYTES; ++step) { - for (i = 0; i < BLAKE2_KAT_LENGTH; ++i) { - uint8_t hash[BLAKE2B_OUTBYTES]; - blake2b_state S; - uint8_t * p = buf; - size_t mlen = i; - int err = 0; - - if ((err = blake2b_init_key(&S, BLAKE2B_OUTBYTES, key, BLAKE2B_KEYBYTES)) < 0) { - goto fail; - } - - while (mlen >= step) { - blake2b_update(&S, p, step); - mlen -= step; - p += step; - } - blake2b_update(&S, p, mlen); - if ((err = blake2b_final(&S, hash, BLAKE2B_OUTBYTES)) < 0) { - goto fail; - } - - if (0 != memcmp(hash, blake2b_keyed_kat[i], BLAKE2B_OUTBYTES)) { - goto fail; - } - } - } - - puts("ok"); - return 0; + puts("ok"); + return 0; fail: - puts("error"); - return -1; + puts("error"); + return -1; } #endif -#endif // BLAKE2_UNUSED +#endif // BLAKE2_UNUSED -#endif // HAVE_BLAKE2 +#endif // HAVE_BLAKE2 diff --git a/lib_cxng/src/cx_blake2b.h b/lib_cxng/src/cx_blake2b.h index 09e81a1ea..e8657ed13 100644 --- a/lib_cxng/src/cx_blake2b.h +++ b/lib_cxng/src/cx_blake2b.h @@ -1,20 +1,20 @@ /******************************************************************************* -* Ledger Nano S - Secure firmware -* (c) 2022 Ledger -* -* Licensed under the Apache License, Version 2.0 (the "License"); -* you may not use this file except in compliance with the License. -* You may obtain a copy of the License at -* -* http://www.apache.org/licenses/LICENSE-2.0 -* -* Unless required by applicable law or agreed to in writing, software -* distributed under the License is distributed on an "AS IS" BASIS, -* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -* See the License for the specific language governing permissions and -* limitations under the License. -********************************************************************************/ + * Ledger Nano S - Secure firmware + * (c) 2022 Ledger + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + ********************************************************************************/ #ifdef HAVE_BLAKE2 @@ -30,7 +30,7 @@ extern const cx_hash_info_t cx_blake2b_info; cx_err_t cx_blake2b_update(cx_blake2b_t *ctx, const uint8_t *data, size_t len); cx_err_t cx_blake2b_final(cx_blake2b_t *ctx, uint8_t *digest); -size_t cx_blake2b_get_output_size(const cx_blake2b_t *ctx); +size_t cx_blake2b_get_output_size(const cx_blake2b_t *ctx); struct cx_xblake_s { cx_blake2b_t blake2b; @@ -38,9 +38,9 @@ struct cx_xblake_s { uint64_t v[16]; uint8_t buffer[BLAKE2B_OUTBYTES]; uint8_t block1[BLAKE2B_BLOCKBYTES]; -} ; +}; typedef struct cx_xblake_s cx_xblake_t; -#endif // CX_BLAKE2B_H +#endif // CX_BLAKE2B_H -#endif // HAVE_BLAKE2 +#endif // HAVE_BLAKE2 diff --git a/lib_cxng/src/cx_blake3.c b/lib_cxng/src/cx_blake3.c index b17312829..f715c795a 100644 --- a/lib_cxng/src/cx_blake3.c +++ b/lib_cxng/src/cx_blake3.c @@ -10,19 +10,21 @@ * Initializing the hash context in the default hashing mode. * The key words are the initialization vectors. */ -cx_err_t cx_blake3_init_default(cx_blake3_t *hash) { - blake3_init_ctx(hash, IV, 0); - return CX_OK; +cx_err_t cx_blake3_init_default(cx_blake3_t *hash) +{ + blake3_init_ctx(hash, IV, 0); + return CX_OK; } /** * Initializing the hash context in the keyed hashing mode. */ -cx_err_t cx_blake3_init_keyed(cx_blake3_t *hash, const uint8_t *key) { - uint32_t key_words[BLAKE3_NB_OF_WORDS]; - load_key_words(key, key_words); - blake3_init_ctx(hash, key_words, KEYED_HASH); - return CX_OK; +cx_err_t cx_blake3_init_keyed(cx_blake3_t *hash, const uint8_t *key) +{ + uint32_t key_words[BLAKE3_NB_OF_WORDS]; + load_key_words(key, key_words); + blake3_init_ctx(hash, key_words, KEYED_HASH); + return CX_OK; } /** @@ -30,192 +32,203 @@ cx_err_t cx_blake3_init_keyed(cx_blake3_t *hash, const uint8_t *key) { * context is the context string used as an initialization parameter, * it should be hardcoded, globally unique and application-specific */ -cx_err_t cx_blake3_init_derive_key(cx_blake3_t *hash, const void *context, size_t context_len) { - uint8_t context_key[BLAKE3_KEY_LEN]; - uint32_t context_key_words[BLAKE3_NB_OF_WORDS]; - - // The context string context is hashed with the key words set to IV_0,...,IV_7 - // The DERIVE_KEY_CONTEXT flag is set for every compression - // Then the key material context_key_words is hashed with the key words set to the - // the first 8 output words of the first stage (context_key) - - blake3_init_ctx(hash, IV, DERIVE_KEY_CONTEXT); - cx_blake3_update(hash, context, context_len); - cx_blake3_final(hash, context_key, BLAKE3_KEY_LEN); - load_key_words(context_key, context_key_words); - blake3_init_ctx(hash, context_key_words, DERIVE_KEY_MATERIAL); - - return CX_OK; +cx_err_t cx_blake3_init_derive_key(cx_blake3_t *hash, const void *context, size_t context_len) +{ + uint8_t context_key[BLAKE3_KEY_LEN]; + uint32_t context_key_words[BLAKE3_NB_OF_WORDS]; + + // The context string context is hashed with the key words set to IV_0,...,IV_7 + // The DERIVE_KEY_CONTEXT flag is set for every compression + // Then the key material context_key_words is hashed with the key words set to the + // the first 8 output words of the first stage (context_key) + + blake3_init_ctx(hash, IV, DERIVE_KEY_CONTEXT); + cx_blake3_update(hash, context, context_len); + cx_blake3_final(hash, context_key, BLAKE3_KEY_LEN); + load_key_words(context_key, context_key_words); + blake3_init_ctx(hash, context_key_words, DERIVE_KEY_MATERIAL); + + return CX_OK; } -cx_err_t cx_blake3_init(cx_blake3_t *hash, uint8_t mode, const uint8_t *key, - const void *context, size_t context_len) { - switch (mode) { - case 0: - cx_blake3_init_default(hash); - break; - case KEYED_HASH: - if (NULL == key) { - return CX_INVALID_PARAMETER; - } - cx_blake3_init_keyed(hash, key); - break; - case DERIVE_KEY_CONTEXT: - if ((NULL == context) || (!context_len)) { - return CX_INVALID_PARAMETER; +cx_err_t cx_blake3_init(cx_blake3_t *hash, + uint8_t mode, + const uint8_t *key, + const void *context, + size_t context_len) +{ + switch (mode) { + case 0: + cx_blake3_init_default(hash); + break; + case KEYED_HASH: + if (NULL == key) { + return CX_INVALID_PARAMETER; + } + cx_blake3_init_keyed(hash, key); + break; + case DERIVE_KEY_CONTEXT: + if ((NULL == context) || (!context_len)) { + return CX_INVALID_PARAMETER; + } + cx_blake3_init_derive_key(hash, context, context_len); + break; + default: + return CX_INVALID_PARAMETER; } - cx_blake3_init_derive_key(hash, context, context_len); - break; - default: - return CX_INVALID_PARAMETER; - } - return CX_OK; + return CX_OK; } -cx_err_t cx_blake3_update(cx_blake3_t *hash, const void *input, size_t input_len) { - const uint8_t *input_bytes = (const uint8_t *)input; - size_t state_len; - size_t nb_bytes; +cx_err_t cx_blake3_update(cx_blake3_t *hash, const void *input, size_t input_len) +{ + const uint8_t *input_bytes = (const uint8_t *) input; + size_t state_len; + size_t nb_bytes; - if (!input_len) { - return CX_OK; - } + if (!input_len) { + return CX_OK; + } - state_len = BLAKE3_BLOCK_LEN * (hash->chunk).blocks_compressed + (hash->chunk).buffer_len; + state_len = BLAKE3_BLOCK_LEN * (hash->chunk).blocks_compressed + (hash->chunk).buffer_len; + + if (state_len > 0) { + nb_bytes = BLAKE3_CHUNK_LEN - state_len; + if (nb_bytes > input_len) { + nb_bytes = input_len; + } + blake3_state_update(&hash->chunk, input_bytes, nb_bytes); + input_bytes += nb_bytes; + input_len -= nb_bytes; + + if (input_len > 0) { + cx_blake3_state_out_t output = blake3_state_output(&hash->chunk); + uint8_t chunk_cv[32]; + blake3_output_chain(&output, chunk_cv); + blake3_hasher_push_cv(hash, chunk_cv, (hash->chunk).t); + blake3_state_reset(&hash->chunk, hash->key, (hash->chunk).t + 1); + } + else { + return CX_OK; + } + } - if (state_len > 0) { - nb_bytes = BLAKE3_CHUNK_LEN - state_len; - if (nb_bytes > input_len) { - nb_bytes = input_len; + while (input_len > BLAKE3_CHUNK_LEN) { + size_t subtree_len; + uint64_t count; + uint64_t subtree_chunks; + subtree_len = 1ULL << highest_one(input_len | 1); + count = (hash->chunk).t * BLAKE3_CHUNK_LEN; + + while ((((uint64_t) (subtree_len - 1)) & count) != 0) { + subtree_len /= 2; + } + + subtree_chunks = subtree_len / BLAKE3_CHUNK_LEN; + if (subtree_len <= BLAKE3_CHUNK_LEN) { + cx_blake3_state_t chunk_state; + uint8_t cv[BLAKE3_OUT_LEN]; + blake3_state_init(&chunk_state, hash->key, (hash->chunk).d); + chunk_state.t = (hash->chunk).t; + blake3_state_update(&chunk_state, input_bytes, subtree_len); + cx_blake3_state_out_t output = blake3_state_output(&chunk_state); + blake3_output_chain(&output, cv); + blake3_hasher_push_cv(hash, cv, chunk_state.t); + } + else { + uint8_t cv_pair[2 * BLAKE3_OUT_LEN]; + blake3_compress_subtree_to_parent( + input_bytes, subtree_len, hash->key, (hash->chunk).t, (hash->chunk).d, cv_pair); + blake3_hasher_push_cv(hash, cv_pair, (hash->chunk).t); + blake3_hasher_push_cv( + hash, cv_pair + BLAKE3_OUT_LEN, (hash->chunk).t + (subtree_chunks / 2)); + } + (hash->chunk).t += subtree_chunks; + input_bytes += subtree_len; + input_len -= subtree_len; } - blake3_state_update(&hash->chunk, input_bytes, nb_bytes); - input_bytes += nb_bytes; - input_len -= nb_bytes; if (input_len > 0) { - cx_blake3_state_out_t output = blake3_state_output(&hash->chunk); - uint8_t chunk_cv[32]; - blake3_output_chain(&output, chunk_cv); - blake3_hasher_push_cv(hash, chunk_cv, (hash->chunk).t); - blake3_state_reset(&hash->chunk, hash->key, (hash->chunk).t + 1); - } else { - return CX_OK; + blake3_state_update(&hash->chunk, input_bytes, input_len); + blake3_hasher_merge_cv(hash, (hash->chunk).t); } - } + return CX_OK; +} - while (input_len > BLAKE3_CHUNK_LEN) { - size_t subtree_len; - uint64_t count; - uint64_t subtree_chunks; - subtree_len = 1ULL << highest_one(input_len | 1); - count = (hash->chunk).t * BLAKE3_CHUNK_LEN; +cx_err_t cx_blake3_final(cx_blake3_t *hash, uint8_t *output, size_t out_len) +{ + if (!out_len) { + return CX_INVALID_PARAMETER; + } + cx_blake3_state_out_t chunk_out; - while ((((uint64_t)(subtree_len - 1)) & count) != 0) { - subtree_len /= 2; + // If the subtree stack is empty, then the current chunk is the root. + if (!hash->cv_stack_len) { + chunk_out = blake3_state_output(&hash->chunk); + blake3_output_root_bytes(&chunk_out, output, out_len); + return CX_OK; } - subtree_chunks = subtree_len / BLAKE3_CHUNK_LEN; - if (subtree_len <= BLAKE3_CHUNK_LEN) { - cx_blake3_state_t chunk_state; - uint8_t cv[BLAKE3_OUT_LEN]; - blake3_state_init(&chunk_state, hash->key, (hash->chunk).d); - chunk_state.t = (hash->chunk).t; - blake3_state_update(&chunk_state, input_bytes, subtree_len); - cx_blake3_state_out_t output = blake3_state_output(&chunk_state); - blake3_output_chain(&output, cv); - blake3_hasher_push_cv(hash, cv, chunk_state.t); + size_t cvs_remaining; + size_t state_len + = BLAKE3_BLOCK_LEN * (hash->chunk).blocks_compressed + (hash->chunk).buffer_len; + uint8_t parent_block[BLAKE3_BLOCK_LEN]; + + if (state_len > 0) { + cvs_remaining = hash->cv_stack_len; + chunk_out = blake3_state_output(&hash->chunk); } else { - - uint8_t cv_pair[2 * BLAKE3_OUT_LEN]; - blake3_compress_subtree_to_parent(input_bytes, subtree_len, hash->key, - (hash->chunk).t, - (hash->chunk).d, cv_pair); - blake3_hasher_push_cv(hash, cv_pair, (hash->chunk).t); - blake3_hasher_push_cv(hash, cv_pair + BLAKE3_OUT_LEN, - (hash->chunk).t + (subtree_chunks / 2)); + // There are always at least 2 CVs in the stack in this case. + cvs_remaining = hash->cv_stack_len - 2; + memcpy(chunk_out.input_cv, hash->key, BLAKE3_OUT_LEN); + memcpy(chunk_out.block, hash->cv_stack + cvs_remaining * BLAKE3_OUT_LEN, BLAKE3_BLOCK_LEN); + chunk_out.block_len = BLAKE3_BLOCK_LEN; + chunk_out.counter = 0; + chunk_out.d = (hash->chunk).d | PARENT; + } + while (cvs_remaining > 0) { + cvs_remaining -= 1; + memcpy(parent_block, hash->cv_stack + cvs_remaining * BLAKE3_OUT_LEN, BLAKE3_OUT_LEN); + blake3_output_chain(&chunk_out, parent_block + BLAKE3_OUT_LEN); + memcpy(chunk_out.input_cv, hash->key, BLAKE3_OUT_LEN); + memcpy(chunk_out.block, parent_block, BLAKE3_BLOCK_LEN); + chunk_out.block_len = BLAKE3_BLOCK_LEN; + chunk_out.counter = 0; + chunk_out.d = (hash->chunk).d | PARENT; } - (hash->chunk).t += subtree_chunks; - input_bytes += subtree_len; - input_len -= subtree_len; - } - - if (input_len > 0) { - blake3_state_update(&hash->chunk, input_bytes, input_len); - blake3_hasher_merge_cv(hash, (hash->chunk).t); - } - return CX_OK; -} - -cx_err_t cx_blake3_final(cx_blake3_t *hash, uint8_t *output, size_t out_len) { - - if (!out_len) { - return CX_INVALID_PARAMETER; - } - cx_blake3_state_out_t chunk_out; - - // If the subtree stack is empty, then the current chunk is the root. - if (!hash->cv_stack_len) { - chunk_out = blake3_state_output(&hash->chunk); blake3_output_root_bytes(&chunk_out, output, out_len); + return CX_OK; - } - - size_t cvs_remaining; - size_t state_len = BLAKE3_BLOCK_LEN * (hash->chunk).blocks_compressed + (hash->chunk).buffer_len; - uint8_t parent_block[BLAKE3_BLOCK_LEN]; - - if (state_len > 0) { - cvs_remaining = hash->cv_stack_len; - chunk_out = blake3_state_output(&hash->chunk); - } - else { - // There are always at least 2 CVs in the stack in this case. - cvs_remaining = hash->cv_stack_len - 2; - memcpy(chunk_out.input_cv, hash->key, BLAKE3_OUT_LEN); - memcpy(chunk_out.block, hash->cv_stack + cvs_remaining * BLAKE3_OUT_LEN, BLAKE3_BLOCK_LEN); - chunk_out.block_len = BLAKE3_BLOCK_LEN; - chunk_out.counter = 0; - chunk_out.d = (hash->chunk).d | PARENT; - - } - while (cvs_remaining > 0) { - cvs_remaining -= 1; - memcpy(parent_block, hash->cv_stack + cvs_remaining * BLAKE3_OUT_LEN, BLAKE3_OUT_LEN); - blake3_output_chain(&chunk_out, parent_block + BLAKE3_OUT_LEN); - memcpy(chunk_out.input_cv, hash->key, BLAKE3_OUT_LEN); - memcpy(chunk_out.block, parent_block, BLAKE3_BLOCK_LEN); - chunk_out.block_len = BLAKE3_BLOCK_LEN; - chunk_out.counter = 0; - chunk_out.d = (hash->chunk).d | PARENT; - } - blake3_output_root_bytes(&chunk_out, output, out_len); - - return CX_OK; } -static bool cx_blake3_validate_context(const cx_blake3_t *hash) { - if ((NULL == hash) || !hash->is_init) { - return false; - } - return true; +static bool cx_blake3_validate_context(const cx_blake3_t *hash) +{ + if ((NULL == hash) || !hash->is_init) { + return false; + } + return true; } -cx_err_t cx_blake3(cx_blake3_t *hash, uint8_t mode, const void *input, - size_t input_len, uint8_t *out, size_t out_len) { - cx_err_t error; - // Check the context - if (!cx_blake3_validate_context(hash)) { - return CX_INTERNAL_ERROR; - } - CX_CHECK(cx_blake3_update(hash, input, input_len)); - - if (mode & LAST) { - CX_CHECK(cx_blake3_final(hash, out, out_len)); - } - error = CX_OK; - end: +cx_err_t cx_blake3(cx_blake3_t *hash, + uint8_t mode, + const void *input, + size_t input_len, + uint8_t *out, + size_t out_len) +{ + cx_err_t error; + // Check the context + if (!cx_blake3_validate_context(hash)) { + return CX_INTERNAL_ERROR; + } + CX_CHECK(cx_blake3_update(hash, input, input_len)); + + if (mode & LAST) { + CX_CHECK(cx_blake3_final(hash, out, out_len)); + } + error = CX_OK; +end: return error; } -#endif // HAVE_BLAKE3 +#endif // HAVE_BLAKE3 diff --git a/lib_cxng/src/cx_blake3.h b/lib_cxng/src/cx_blake3.h index feda2f1f7..a7e1ae806 100644 --- a/lib_cxng/src/cx_blake3.h +++ b/lib_cxng/src/cx_blake3.h @@ -8,41 +8,48 @@ #include #include "cx_errors.h" -#define BLAKE3_KEY_LEN 32 -#define BLAKE3_CHUNK_LEN 1024 +#define BLAKE3_KEY_LEN 32 +#define BLAKE3_CHUNK_LEN 1024 enum blake3_flags { - CHUNK_START = 1 << 0, - CHUNK_END = 1 << 1, - PARENT = 1 << 2, - ROOT = 1 << 3, - KEYED_HASH = 1 << 4, - DERIVE_KEY_CONTEXT = 1 << 5, - DERIVE_KEY_MATERIAL = 1 << 6, - LAST = 1 << 7, + CHUNK_START = 1 << 0, + CHUNK_END = 1 << 1, + PARENT = 1 << 2, + ROOT = 1 << 3, + KEYED_HASH = 1 << 4, + DERIVE_KEY_CONTEXT = 1 << 5, + DERIVE_KEY_MATERIAL = 1 << 6, + LAST = 1 << 7, }; typedef struct { - uint32_t input_cv[BLAKE3_NB_OF_WORDS]; - uint64_t counter; - uint8_t block[BLAKE3_BLOCK_LEN]; - uint8_t block_len; - uint8_t d; + uint32_t input_cv[BLAKE3_NB_OF_WORDS]; + uint64_t counter; + uint8_t block[BLAKE3_BLOCK_LEN]; + uint8_t block_len; + uint8_t d; } cx_blake3_state_out_t; // Initialization vectors -static const uint32_t IV[8] = {0x6A09E667UL, 0xBB67AE85UL, 0x3C6EF372UL, - 0xA54FF53AUL, 0x510E527FUL, 0x9B05688CUL, - 0x1F83D9ABUL, 0x5BE0CD19UL}; +static const uint32_t IV[8] = {0x6A09E667UL, + 0xBB67AE85UL, + 0x3C6EF372UL, + 0xA54FF53AUL, + 0x510E527FUL, + 0x9B05688CUL, + 0x1F83D9ABUL, + 0x5BE0CD19UL}; // Permutational key schedule used to permute the message words after each round // of the compression function -static const uint8_t MSG_SCHEDULE[7][16] = {{0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15}, - {2, 6, 3, 10, 7, 0, 4, 13, 1, 11, 12, 5, 9, 14, 15, 8}, - {3, 4, 10, 12, 13, 2, 7, 14, 6, 5, 9, 0, 11, 15, 8, 1}, - {10, 7, 12, 9, 14, 3, 13, 15, 4, 0, 11, 2, 5, 8, 1, 6}, - {12, 13, 9, 11, 15, 10, 14, 8, 7, 2, 5, 3, 0, 1, 6, 4}, - {9, 14, 11, 5, 8, 12, 15, 1, 13, 3, 0, 10, 2, 6, 4, 7}, - {11, 15, 5, 0, 1, 9, 8, 6, 14, 10, 2, 12, 3, 4, 7, 13}}; +static const uint8_t MSG_SCHEDULE[7][16] = { + {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15}, + {2, 6, 3, 10, 7, 0, 4, 13, 1, 11, 12, 5, 9, 14, 15, 8 }, + {3, 4, 10, 12, 13, 2, 7, 14, 6, 5, 9, 0, 11, 15, 8, 1 }, + {10, 7, 12, 9, 14, 3, 13, 15, 4, 0, 11, 2, 5, 8, 1, 6 }, + {12, 13, 9, 11, 15, 10, 14, 8, 7, 2, 5, 3, 0, 1, 6, 4 }, + {9, 14, 11, 5, 8, 12, 15, 1, 13, 3, 0, 10, 2, 6, 4, 7 }, + {11, 15, 5, 0, 1, 9, 8, 6, 14, 10, 2, 12, 3, 4, 7, 13} +}; -#endif // CX_BLAKE3_H -#endif // HAVE_BLAKE3 +#endif // CX_BLAKE3_H +#endif // HAVE_BLAKE3 diff --git a/lib_cxng/src/cx_blake3_ref.c b/lib_cxng/src/cx_blake3_ref.c index 8d5d1465e..922105e84 100644 --- a/lib_cxng/src/cx_blake3_ref.c +++ b/lib_cxng/src/cx_blake3_ref.c @@ -7,75 +7,80 @@ #include /* ---------------------------------------------------------------------------------------------------*/ -/* Functions from the reference implementation */ +/* Functions from the reference implementation */ /* ---------------------------------------------------------------------------------------------------*/ /********************* Compression function ************************/ // The 'quarter-round' function G_i(a,b,c,d) -static void g(uint32_t *state, size_t a, size_t b, size_t c, size_t d, - uint32_t x, uint32_t y) { - state[a] = state[a] + state[b] + x; - state[d] = rotr32(state[d] ^ state[a], 16); - state[c] = state[c] + state[d]; - state[b] = rotr32(state[b] ^ state[c], 12); - state[a] = state[a] + state[b] + y; - state[d] = rotr32(state[d] ^ state[a], 8); - state[c] = state[c] + state[d]; - state[b] = rotr32(state[b] ^ state[c], 7); +static void g(uint32_t *state, size_t a, size_t b, size_t c, size_t d, uint32_t x, uint32_t y) +{ + state[a] = state[a] + state[b] + x; + state[d] = rotr32(state[d] ^ state[a], 16); + state[c] = state[c] + state[d]; + state[b] = rotr32(state[b] ^ state[c], 12); + state[a] = state[a] + state[b] + y; + state[d] = rotr32(state[d] ^ state[a], 8); + state[c] = state[c] + state[d]; + state[b] = rotr32(state[b] ^ state[c], 7); } // The round function F = |G_0(0,4,8,12) G_1(1,5,9,13) G_2(2,6,10,14) G_3(3,7,11,15)| // |G_4(0,5,10,15) G_5(1,6,11,12) G_6(2,7,8,13) G_7(3,4,9,14) | -static void round_fn(uint32_t state[16], const uint32_t *msg, size_t round) { - // Select the message schedule based on the round. - const uint8_t *schedule = MSG_SCHEDULE[round]; - - // Mix the columns. - g(state, 0, 4, 8, 12, msg[schedule[0]], msg[schedule[1]]); - g(state, 1, 5, 9, 13, msg[schedule[2]], msg[schedule[3]]); - g(state, 2, 6, 10, 14, msg[schedule[4]], msg[schedule[5]]); - g(state, 3, 7, 11, 15, msg[schedule[6]], msg[schedule[7]]); - - // Mix the rows. - g(state, 0, 5, 10, 15, msg[schedule[8]], msg[schedule[9]]); - g(state, 1, 6, 11, 12, msg[schedule[10]], msg[schedule[11]]); - g(state, 2, 7, 8, 13, msg[schedule[12]], msg[schedule[13]]); - g(state, 3, 4, 9, 14, msg[schedule[14]], msg[schedule[15]]); +static void round_fn(uint32_t state[16], const uint32_t *msg, size_t round) +{ + // Select the message schedule based on the round. + const uint8_t *schedule = MSG_SCHEDULE[round]; + + // Mix the columns. + g(state, 0, 4, 8, 12, msg[schedule[0]], msg[schedule[1]]); + g(state, 1, 5, 9, 13, msg[schedule[2]], msg[schedule[3]]); + g(state, 2, 6, 10, 14, msg[schedule[4]], msg[schedule[5]]); + g(state, 3, 7, 11, 15, msg[schedule[6]], msg[schedule[7]]); + + // Mix the rows. + g(state, 0, 5, 10, 15, msg[schedule[8]], msg[schedule[9]]); + g(state, 1, 6, 11, 12, msg[schedule[10]], msg[schedule[11]]); + g(state, 2, 7, 8, 13, msg[schedule[12]], msg[schedule[13]]); + g(state, 3, 4, 9, 14, msg[schedule[14]], msg[schedule[15]]); } // Compressing a block along with a chaining value -static void compress_pre(uint32_t *state, const uint32_t *cv, - const uint8_t *block, uint8_t block_len, - uint64_t counter, uint8_t flags) { - uint32_t block_words[16]; - size_t round; - // First convert the block into 32-byte words - for (int i = 0; i < 16; i++) { - block_words[i] = load32(block + 4 * i); - } - - // Initialize the state - state[0] = cv[0]; - state[1] = cv[1]; - state[2] = cv[2]; - state[3] = cv[3]; - state[4] = cv[4]; - state[5] = cv[5]; - state[6] = cv[6]; - state[7] = cv[7]; - state[8] = IV[0]; - state[9] = IV[1]; - state[10] = IV[2]; - state[11] = IV[3]; - state[12] = (uint32_t)counter; - state[13] = (uint32_t)(counter >> 32); - state[14] = (uint32_t)block_len; - state[15] = (uint32_t)flags; - - for (round = 0; round < 7; round++) { - round_fn(state, &block_words[0], round); - } +static void compress_pre(uint32_t *state, + const uint32_t *cv, + const uint8_t *block, + uint8_t block_len, + uint64_t counter, + uint8_t flags) +{ + uint32_t block_words[16]; + size_t round; + // First convert the block into 32-byte words + for (int i = 0; i < 16; i++) { + block_words[i] = load32(block + 4 * i); + } + + // Initialize the state + state[0] = cv[0]; + state[1] = cv[1]; + state[2] = cv[2]; + state[3] = cv[3]; + state[4] = cv[4]; + state[5] = cv[5]; + state[6] = cv[6]; + state[7] = cv[7]; + state[8] = IV[0]; + state[9] = IV[1]; + state[10] = IV[2]; + state[11] = IV[3]; + state[12] = (uint32_t) counter; + state[13] = (uint32_t) (counter >> 32); + state[14] = (uint32_t) block_len; + state[15] = (uint32_t) flags; + + for (round = 0; round < 7; round++) { + round_fn(state, &block_words[0], round); + } } /** @@ -95,19 +100,22 @@ static void compress_pre(uint32_t *state, const uint32_t *cv, * @param[in] flags Flags associated to the block. * */ -static void blake3_compress_in_place(uint32_t *cv, const uint8_t *block, - uint8_t block_len, uint64_t counter, - uint8_t flags) { - uint32_t state[16]; - compress_pre(&state[0], cv, block, block_len, counter, flags); - cv[0] = state[0] ^ state[8]; - cv[1] = state[1] ^ state[9]; - cv[2] = state[2] ^ state[10]; - cv[3] = state[3] ^ state[11]; - cv[4] = state[4] ^ state[12]; - cv[5] = state[5] ^ state[13]; - cv[6] = state[6] ^ state[14]; - cv[7] = state[7] ^ state[15]; +static void blake3_compress_in_place(uint32_t *cv, + const uint8_t *block, + uint8_t block_len, + uint64_t counter, + uint8_t flags) +{ + uint32_t state[16]; + compress_pre(&state[0], cv, block, block_len, counter, flags); + cv[0] = state[0] ^ state[8]; + cv[1] = state[1] ^ state[9]; + cv[2] = state[2] ^ state[10]; + cv[3] = state[3] ^ state[11]; + cv[4] = state[4] ^ state[12]; + cv[5] = state[5] ^ state[13]; + cv[6] = state[6] ^ state[14]; + cv[7] = state[7] ^ state[15]; } /** @@ -127,28 +135,32 @@ static void blake3_compress_in_place(uint32_t *cv, const uint8_t *block, * * @param[out] out Full output of the compression function (64 bytes). */ -static void blake3_compress_xof(const uint32_t *cv, const uint8_t *block, - uint8_t block_len, uint64_t counter, - uint8_t flags, uint8_t *out) { - uint32_t state[16]; - compress_pre(state, cv, block, block_len, counter, flags); - - store32(&out[0 * 4], state[0] ^ state[8]); - store32(&out[1 * 4], state[1] ^ state[9]); - store32(&out[2 * 4], state[2] ^ state[10]); - store32(&out[3 * 4], state[3] ^ state[11]); - store32(&out[4 * 4], state[4] ^ state[12]); - store32(&out[5 * 4], state[5] ^ state[13]); - store32(&out[6 * 4], state[6] ^ state[14]); - store32(&out[7 * 4], state[7] ^ state[15]); - store32(&out[8 * 4], state[8] ^ cv[0]); - store32(&out[9 * 4], state[9] ^ cv[1]); - store32(&out[10 * 4], state[10] ^ cv[2]); - store32(&out[11 * 4], state[11] ^ cv[3]); - store32(&out[12 * 4], state[12] ^ cv[4]); - store32(&out[13 * 4], state[13] ^ cv[5]); - store32(&out[14 * 4], state[14] ^ cv[6]); - store32(&out[15 * 4], state[15] ^ cv[7]); +static void blake3_compress_xof(const uint32_t *cv, + const uint8_t *block, + uint8_t block_len, + uint64_t counter, + uint8_t flags, + uint8_t *out) +{ + uint32_t state[16]; + compress_pre(state, cv, block, block_len, counter, flags); + + store32(&out[0 * 4], state[0] ^ state[8]); + store32(&out[1 * 4], state[1] ^ state[9]); + store32(&out[2 * 4], state[2] ^ state[10]); + store32(&out[3 * 4], state[3] ^ state[11]); + store32(&out[4 * 4], state[4] ^ state[12]); + store32(&out[5 * 4], state[5] ^ state[13]); + store32(&out[6 * 4], state[6] ^ state[14]); + store32(&out[7 * 4], state[7] ^ state[15]); + store32(&out[8 * 4], state[8] ^ cv[0]); + store32(&out[9 * 4], state[9] ^ cv[1]); + store32(&out[10 * 4], state[10] ^ cv[2]); + store32(&out[11 * 4], state[11] ^ cv[3]); + store32(&out[12 * 4], state[12] ^ cv[4]); + store32(&out[13 * 4], state[13] ^ cv[5]); + store32(&out[14 * 4], state[14] ^ cv[6]); + store32(&out[15 * 4], state[15] ^ cv[7]); } /******************** Chunk state functions *********************/ @@ -163,101 +175,108 @@ static void blake3_compress_xof(const uint32_t *cv, const uint8_t *block, * * @return Current size of the buffer. */ -static size_t blake3_fill_buffer(cx_blake3_state_t *chunk_state, const uint8_t *input, size_t input_len) { - size_t nb_bytes = BLAKE3_BLOCK_LEN - ((size_t)chunk_state->buffer_len); - if (nb_bytes > input_len) { - nb_bytes = input_len; - } - memcpy(chunk_state->buffer + ((size_t)chunk_state->buffer_len), input, nb_bytes); - chunk_state->buffer_len += (uint8_t)nb_bytes; - - return nb_bytes; +static size_t blake3_fill_buffer(cx_blake3_state_t *chunk_state, + const uint8_t *input, + size_t input_len) +{ + size_t nb_bytes = BLAKE3_BLOCK_LEN - ((size_t) chunk_state->buffer_len); + if (nb_bytes > input_len) { + nb_bytes = input_len; + } + memcpy(chunk_state->buffer + ((size_t) chunk_state->buffer_len), input, nb_bytes); + chunk_state->buffer_len += (uint8_t) nb_bytes; + + return nb_bytes; } -void blake3_state_init(cx_blake3_state_t *chunk_state, const uint32_t *key, - uint8_t flags) { - memcpy(chunk_state->cv, key, BLAKE3_KEY_LEN); - chunk_state->t = 0; - memset(chunk_state->buffer, 0, BLAKE3_BLOCK_LEN); - chunk_state->buffer_len = 0; - chunk_state->blocks_compressed = 0; - chunk_state->d = flags; +void blake3_state_init(cx_blake3_state_t *chunk_state, const uint32_t *key, uint8_t flags) +{ + memcpy(chunk_state->cv, key, BLAKE3_KEY_LEN); + chunk_state->t = 0; + memset(chunk_state->buffer, 0, BLAKE3_BLOCK_LEN); + chunk_state->buffer_len = 0; + chunk_state->blocks_compressed = 0; + chunk_state->d = flags; } -void blake3_state_update(cx_blake3_state_t *chunk_state, const uint8_t *input, - size_t input_len) { - size_t nb_bytes; - uint8_t is_start_flag = 0; - if (chunk_state->buffer_len > 0) { - nb_bytes = blake3_fill_buffer(chunk_state, input, input_len); - input += nb_bytes; - input_len -= nb_bytes; - if (input_len > 0) { - if (!chunk_state->blocks_compressed) { - is_start_flag = CHUNK_START; - } - blake3_compress_in_place(chunk_state->cv, chunk_state->buffer, - BLAKE3_BLOCK_LEN, chunk_state->t, - chunk_state->d | is_start_flag); - chunk_state->blocks_compressed += 1; - chunk_state->buffer_len = 0; - memset(chunk_state->buffer, 0, BLAKE3_BLOCK_LEN); +void blake3_state_update(cx_blake3_state_t *chunk_state, const uint8_t *input, size_t input_len) +{ + size_t nb_bytes; + uint8_t is_start_flag = 0; + if (chunk_state->buffer_len > 0) { + nb_bytes = blake3_fill_buffer(chunk_state, input, input_len); + input += nb_bytes; + input_len -= nb_bytes; + if (input_len > 0) { + if (!chunk_state->blocks_compressed) { + is_start_flag = CHUNK_START; + } + blake3_compress_in_place(chunk_state->cv, + chunk_state->buffer, + BLAKE3_BLOCK_LEN, + chunk_state->t, + chunk_state->d | is_start_flag); + chunk_state->blocks_compressed += 1; + chunk_state->buffer_len = 0; + memset(chunk_state->buffer, 0, BLAKE3_BLOCK_LEN); + } } - } - while (input_len > BLAKE3_BLOCK_LEN) { - if (!chunk_state->blocks_compressed) { - is_start_flag = CHUNK_START; - } - else { - is_start_flag = 0; + while (input_len > BLAKE3_BLOCK_LEN) { + if (!chunk_state->blocks_compressed) { + is_start_flag = CHUNK_START; + } + else { + is_start_flag = 0; + } + blake3_compress_in_place(chunk_state->cv, + input, + BLAKE3_BLOCK_LEN, + chunk_state->t, + chunk_state->d | is_start_flag); + chunk_state->blocks_compressed += 1; + input += BLAKE3_BLOCK_LEN; + input_len -= BLAKE3_BLOCK_LEN; } - blake3_compress_in_place(chunk_state->cv, input, BLAKE3_BLOCK_LEN, - chunk_state->t, - chunk_state->d | is_start_flag); - chunk_state->blocks_compressed += 1; - input += BLAKE3_BLOCK_LEN; - input_len -= BLAKE3_BLOCK_LEN; - } - - nb_bytes = blake3_fill_buffer(chunk_state, input, input_len); -} -void blake3_state_reset(cx_blake3_state_t *chunk_state, const uint32_t *key, - uint64_t chunk_counter) { - memcpy(chunk_state->cv, key, BLAKE3_KEY_LEN); - chunk_state->t = chunk_counter; - chunk_state->blocks_compressed = 0; - memset(chunk_state->buffer, 0, BLAKE3_BLOCK_LEN); - chunk_state->buffer_len = 0; + nb_bytes = blake3_fill_buffer(chunk_state, input, input_len); } -cx_blake3_state_out_t blake3_state_output(const cx_blake3_state_t *chunk_state) { - uint8_t is_start_flag = 0; - uint8_t block_flags; - cx_blake3_state_out_t chunk_output; - - if (!chunk_state->blocks_compressed) { - is_start_flag = CHUNK_START; - } - block_flags = chunk_state->d | is_start_flag | CHUNK_END; - memcpy(chunk_output.input_cv, chunk_state->cv, BLAKE3_OUT_LEN); - memcpy(chunk_output.block, chunk_state->buffer, BLAKE3_BLOCK_LEN); - chunk_output.block_len = chunk_state->buffer_len; - chunk_output.counter = chunk_state->t; - chunk_output.d = block_flags; - - return chunk_output; +void blake3_state_reset(cx_blake3_state_t *chunk_state, const uint32_t *key, uint64_t chunk_counter) +{ + memcpy(chunk_state->cv, key, BLAKE3_KEY_LEN); + chunk_state->t = chunk_counter; + chunk_state->blocks_compressed = 0; + memset(chunk_state->buffer, 0, BLAKE3_BLOCK_LEN); + chunk_state->buffer_len = 0; } -void blake3_output_chain(const cx_blake3_state_out_t *out, uint8_t *cv) { - uint32_t cv_words[BLAKE3_NB_OF_WORDS]; - memcpy(cv_words, out->input_cv, BLAKE3_WORD_SIZE); - blake3_compress_in_place(cv_words, out->block, out->block_len, - out->counter, out->d); - store_cv_words(cv, cv_words); +cx_blake3_state_out_t blake3_state_output(const cx_blake3_state_t *chunk_state) +{ + uint8_t is_start_flag = 0; + uint8_t block_flags; + cx_blake3_state_out_t chunk_output; + + if (!chunk_state->blocks_compressed) { + is_start_flag = CHUNK_START; + } + block_flags = chunk_state->d | is_start_flag | CHUNK_END; + memcpy(chunk_output.input_cv, chunk_state->cv, BLAKE3_OUT_LEN); + memcpy(chunk_output.block, chunk_state->buffer, BLAKE3_BLOCK_LEN); + chunk_output.block_len = chunk_state->buffer_len; + chunk_output.counter = chunk_state->t; + chunk_output.d = block_flags; + + return chunk_output; } +void blake3_output_chain(const cx_blake3_state_out_t *out, uint8_t *cv) +{ + uint32_t cv_words[BLAKE3_NB_OF_WORDS]; + memcpy(cv_words, out->input_cv, BLAKE3_WORD_SIZE); + blake3_compress_in_place(cv_words, out->block, out->block_len, out->counter, out->d); + store_cv_words(cv, cv_words); +} /********************* Hashing ************************/ /** @@ -281,24 +300,28 @@ void blake3_output_chain(const cx_blake3_state_out_t *out, uint8_t *cv) { * * @param[out] out Output of the compression: a 32-byte chaining value. */ -static void blake3_hash_one(const uint8_t *input, size_t blocks, - const uint32_t *key, uint64_t counter, - uint8_t flags, uint8_t flags_start, - uint8_t flags_end, uint8_t *out) { - uint32_t cv[BLAKE3_NB_OF_WORDS]; - memcpy(cv, key, BLAKE3_KEY_LEN); - uint8_t block_flags = flags | flags_start; - while (blocks > 0) { - if (1 == blocks) { - block_flags |= flags_end; +static void blake3_hash_one(const uint8_t *input, + size_t blocks, + const uint32_t *key, + uint64_t counter, + uint8_t flags, + uint8_t flags_start, + uint8_t flags_end, + uint8_t *out) +{ + uint32_t cv[BLAKE3_NB_OF_WORDS]; + memcpy(cv, key, BLAKE3_KEY_LEN); + uint8_t block_flags = flags | flags_start; + while (blocks > 0) { + if (1 == blocks) { + block_flags |= flags_end; + } + blake3_compress_in_place(cv, input, BLAKE3_BLOCK_LEN, counter, block_flags); + input = &input[BLAKE3_BLOCK_LEN]; + blocks -= 1; + block_flags = flags; } - blake3_compress_in_place(cv, input, BLAKE3_BLOCK_LEN, - counter, block_flags); - input = &input[BLAKE3_BLOCK_LEN]; - blocks -= 1; - block_flags = flags; - } - store_cv_words(out, cv); + store_cv_words(out, cv); } /** @@ -324,21 +347,26 @@ static void blake3_hash_one(const uint8_t *input, size_t blocks, * * @param[out] out Outputs of the compression. */ -static void blake3_hash_many(const uint8_t *const *inputs, size_t num_inputs, - size_t blocks, const uint32_t *key, - uint64_t counter, bool increment_counter, - uint8_t flags, uint8_t flags_start, - uint8_t flags_end, uint8_t *out) { - while (num_inputs > 0) { - blake3_hash_one(inputs[0], blocks, key, counter, flags, flags_start, - flags_end, out); - if (increment_counter) { - counter += 1; +static void blake3_hash_many(const uint8_t *const *inputs, + size_t num_inputs, + size_t blocks, + const uint32_t *key, + uint64_t counter, + bool increment_counter, + uint8_t flags, + uint8_t flags_start, + uint8_t flags_end, + uint8_t *out) +{ + while (num_inputs > 0) { + blake3_hash_one(inputs[0], blocks, key, counter, flags, flags_start, flags_end, out); + if (increment_counter) { + counter += 1; + } + inputs += 1; + num_inputs -= 1; + out = &out[BLAKE3_OUT_LEN]; } - inputs += 1; - num_inputs -= 1; - out = &out[BLAKE3_OUT_LEN]; - } } /** @@ -361,40 +389,50 @@ static void blake3_hash_many(const uint8_t *const *inputs, size_t num_inputs, * @return Length of the chunk array * (if several chunks have been compressed in parallel). */ -static size_t blake3_compress_chunks(const uint8_t *input, size_t input_len, - const uint32_t *key, uint64_t chunk_counter, - uint8_t flags, uint8_t *out) { - - const uint8_t *chunks_array[1]; - size_t input_position = 0; - size_t chunks_array_len = 0; - cx_blake3_state_out_t output; - - while (input_len - input_position >= BLAKE3_CHUNK_LEN) { - chunks_array[chunks_array_len] = &input[input_position]; - input_position += BLAKE3_CHUNK_LEN; - chunks_array_len += 1; - } - - blake3_hash_many(chunks_array, chunks_array_len, - BLAKE3_CHUNK_LEN / BLAKE3_BLOCK_LEN, key, chunk_counter, - true, flags, CHUNK_START, CHUNK_END, out); - - // Hash the remaining partial chunk, if there is one. Note that the empty - // chunk (meaning the empty message) is a different codepath. - if (input_len > input_position) { - uint64_t counter = chunk_counter + (uint64_t)chunks_array_len; - cx_blake3_state_t chunk_state; - blake3_state_init(&chunk_state, key, flags); - chunk_state.t = counter; - blake3_state_update(&chunk_state, input + input_position, input_len - input_position); - output = blake3_state_output(&chunk_state); - blake3_output_chain(&output, out + chunks_array_len * BLAKE3_OUT_LEN); - return chunks_array_len + 1; - } - else { - return chunks_array_len; - } +static size_t blake3_compress_chunks(const uint8_t *input, + size_t input_len, + const uint32_t *key, + uint64_t chunk_counter, + uint8_t flags, + uint8_t *out) +{ + const uint8_t *chunks_array[1]; + size_t input_position = 0; + size_t chunks_array_len = 0; + cx_blake3_state_out_t output; + + while (input_len - input_position >= BLAKE3_CHUNK_LEN) { + chunks_array[chunks_array_len] = &input[input_position]; + input_position += BLAKE3_CHUNK_LEN; + chunks_array_len += 1; + } + + blake3_hash_many(chunks_array, + chunks_array_len, + BLAKE3_CHUNK_LEN / BLAKE3_BLOCK_LEN, + key, + chunk_counter, + true, + flags, + CHUNK_START, + CHUNK_END, + out); + + // Hash the remaining partial chunk, if there is one. Note that the empty + // chunk (meaning the empty message) is a different codepath. + if (input_len > input_position) { + uint64_t counter = chunk_counter + (uint64_t) chunks_array_len; + cx_blake3_state_t chunk_state; + blake3_state_init(&chunk_state, key, flags); + chunk_state.t = counter; + blake3_state_update(&chunk_state, input + input_position, input_len - input_position); + output = blake3_state_output(&chunk_state); + blake3_output_chain(&output, out + chunks_array_len * BLAKE3_OUT_LEN); + return chunks_array_len + 1; + } + else { + return chunks_array_len; + } } /** @@ -408,40 +446,48 @@ static size_t blake3_compress_chunks(const uint8_t *input, size_t input_len, * * @param[in] flags Flags used for the compression. * - * @param[out] out Output of the compression (the chaining value of a parent node). + * @param[out] out Output of the compression (the chaining value of a parent + * node). * - * @return Length of the parents array, i.e. the number of compressed parent nodes + * @return Length of the parents array, i.e. the number of compressed + * parent nodes */ -static size_t blake3_compress_parents(const uint8_t *child_chaining_values, - size_t num_chaining_values, - const uint32_t *key, uint8_t flags, - uint8_t *out) { - - const uint8_t *parents_array[2]; - size_t parents_array_len = 0; - - while (num_chaining_values - (2 * parents_array_len) >= 2) { - parents_array[parents_array_len] = &child_chaining_values[2 * parents_array_len * BLAKE3_OUT_LEN]; - parents_array_len += 1; - } - - blake3_hash_many(parents_array, parents_array_len, 1, key, - 0, // Parents always use counter 0. - false, flags | PARENT, - 0, // Parents have no start flags. - 0, // Parents have no end flags. - out); - - // If there's an odd child left over, it becomes an output. - if (num_chaining_values > 2 * parents_array_len) { - memcpy(out + parents_array_len * BLAKE3_OUT_LEN, - child_chaining_values + 2 * parents_array_len * BLAKE3_OUT_LEN, - BLAKE3_OUT_LEN); - return parents_array_len + 1; - } - else { - return parents_array_len; - } +static size_t blake3_compress_parents(const uint8_t *child_chaining_values, + size_t num_chaining_values, + const uint32_t *key, + uint8_t flags, + uint8_t *out) +{ + const uint8_t *parents_array[2]; + size_t parents_array_len = 0; + + while (num_chaining_values - (2 * parents_array_len) >= 2) { + parents_array[parents_array_len] + = &child_chaining_values[2 * parents_array_len * BLAKE3_OUT_LEN]; + parents_array_len += 1; + } + + blake3_hash_many(parents_array, + parents_array_len, + 1, + key, + 0, // Parents always use counter 0. + false, + flags | PARENT, + 0, // Parents have no start flags. + 0, // Parents have no end flags. + out); + + // If there's an odd child left over, it becomes an output. + if (num_chaining_values > 2 * parents_array_len) { + memcpy(out + parents_array_len * BLAKE3_OUT_LEN, + child_chaining_values + 2 * parents_array_len * BLAKE3_OUT_LEN, + BLAKE3_OUT_LEN); + return parents_array_len + 1; + } + else { + return parents_array_len; + } } /** @@ -461,117 +507,129 @@ static size_t blake3_compress_parents(const uint8_t *child_chaining_values, * * @return Number of compressed nodes. */ -static size_t blake3_compress_subtree(const uint8_t *input, size_t input_len, - const uint32_t *key, uint64_t chunk_counter, - uint8_t flags, uint8_t *out) { - - // One chunk - if (input_len <= BLAKE3_CHUNK_LEN) { - return blake3_compress_chunks(input, input_len, key, chunk_counter, flags, out); - } - - // At least two chunks - // The left subtree consists of the first 2^(10+log((n-1)/1024)), where n is the input length - // and he right substree consists of the remainder - size_t left_input_len = 1ULL << highest_one(((input_len - 1) / BLAKE3_CHUNK_LEN) | 1); - left_input_len = left_input_len * BLAKE3_CHUNK_LEN; - size_t right_input_len = input_len - left_input_len; - const uint8_t *right_input = &input[left_input_len]; - uint64_t right_chunk_counter = chunk_counter + (uint64_t)(left_input_len / BLAKE3_CHUNK_LEN); - - uint8_t cv_array[2 * 2 * BLAKE3_OUT_LEN]; - size_t degree = 1; - uint8_t *right_cvs; - size_t left_n, right_n; - - if (left_input_len > BLAKE3_CHUNK_LEN) { - degree = 2; - } - right_cvs = &cv_array[degree * BLAKE3_OUT_LEN]; - - left_n = blake3_compress_subtree(input, left_input_len, key, - chunk_counter, flags, cv_array); - right_n = blake3_compress_subtree(right_input, right_input_len, key, - right_chunk_counter, flags, right_cvs); - - if (1 == left_n) { - memcpy(out, cv_array, 2 * BLAKE3_OUT_LEN); - return 2; - } +static size_t blake3_compress_subtree(const uint8_t *input, + size_t input_len, + const uint32_t *key, + uint64_t chunk_counter, + uint8_t flags, + uint8_t *out) +{ + // One chunk + if (input_len <= BLAKE3_CHUNK_LEN) { + return blake3_compress_chunks(input, input_len, key, chunk_counter, flags, out); + } - // Otherwise, do one layer of parent node compression. - size_t num_chaining_values = left_n + right_n; - return blake3_compress_parents(cv_array, num_chaining_values, key, flags, out); -} + // At least two chunks + // The left subtree consists of the first 2^(10+log((n-1)/1024)), where n is the input length + // and he right substree consists of the remainder + size_t left_input_len = 1ULL << highest_one(((input_len - 1) / BLAKE3_CHUNK_LEN) | 1); + left_input_len = left_input_len * BLAKE3_CHUNK_LEN; + size_t right_input_len = input_len - left_input_len; + const uint8_t *right_input = &input[left_input_len]; + uint64_t right_chunk_counter = chunk_counter + (uint64_t) (left_input_len / BLAKE3_CHUNK_LEN); + + uint8_t cv_array[2 * 2 * BLAKE3_OUT_LEN]; + size_t degree = 1; + uint8_t *right_cvs; + size_t left_n, right_n; + + if (left_input_len > BLAKE3_CHUNK_LEN) { + degree = 2; + } + right_cvs = &cv_array[degree * BLAKE3_OUT_LEN]; -void blake3_compress_subtree_to_parent(const uint8_t *input, size_t input_len, const uint32_t *key, - uint64_t chunk_counter, uint8_t flags, uint8_t *out) { + left_n = blake3_compress_subtree(input, left_input_len, key, chunk_counter, flags, cv_array); + right_n = blake3_compress_subtree( + right_input, right_input_len, key, right_chunk_counter, flags, right_cvs); + + if (1 == left_n) { + memcpy(out, cv_array, 2 * BLAKE3_OUT_LEN); + return 2; + } - uint8_t cv_array[2 * BLAKE3_OUT_LEN]; - size_t num_cvs = blake3_compress_subtree(input, input_len, key, - chunk_counter, flags, cv_array); + // Otherwise, do one layer of parent node compression. + size_t num_chaining_values = left_n + right_n; + return blake3_compress_parents(cv_array, num_chaining_values, key, flags, out); +} - uint8_t out_array[BLAKE3_OUT_LEN]; - while (num_cvs > 2) { - num_cvs = blake3_compress_parents(cv_array, num_cvs, key, flags, out_array); - memcpy(cv_array, out_array, num_cvs * BLAKE3_OUT_LEN); - } - memcpy(out, cv_array, 2 * BLAKE3_OUT_LEN); +void blake3_compress_subtree_to_parent(const uint8_t *input, + size_t input_len, + const uint32_t *key, + uint64_t chunk_counter, + uint8_t flags, + uint8_t *out) +{ + uint8_t cv_array[2 * BLAKE3_OUT_LEN]; + size_t num_cvs = blake3_compress_subtree(input, input_len, key, chunk_counter, flags, cv_array); + + uint8_t out_array[BLAKE3_OUT_LEN]; + while (num_cvs > 2) { + num_cvs = blake3_compress_parents(cv_array, num_cvs, key, flags, out_array); + memcpy(cv_array, out_array, num_cvs * BLAKE3_OUT_LEN); + } + memcpy(out, cv_array, 2 * BLAKE3_OUT_LEN); } -void blake3_hasher_merge_cv(cx_blake3_t *hash, uint64_t total_len) { - size_t post_merge_stack_len = (size_t)hw(total_len); - cx_blake3_state_out_t output; - uint8_t *parent_node; - - while (hash->cv_stack_len > post_merge_stack_len) { - parent_node = hash->cv_stack + (hash->cv_stack_len - 2) * BLAKE3_OUT_LEN; - memcpy(output.input_cv, hash->key, BLAKE3_OUT_LEN); - memcpy(output.block, parent_node, BLAKE3_BLOCK_LEN); - output.block_len = BLAKE3_BLOCK_LEN; - output.counter = 0; - output.d = (hash->chunk).d | PARENT; - blake3_output_chain(&output, parent_node); - hash->cv_stack_len -= 1; - } +void blake3_hasher_merge_cv(cx_blake3_t *hash, uint64_t total_len) +{ + size_t post_merge_stack_len = (size_t) hw(total_len); + cx_blake3_state_out_t output; + uint8_t *parent_node; + + while (hash->cv_stack_len > post_merge_stack_len) { + parent_node = hash->cv_stack + (hash->cv_stack_len - 2) * BLAKE3_OUT_LEN; + memcpy(output.input_cv, hash->key, BLAKE3_OUT_LEN); + memcpy(output.block, parent_node, BLAKE3_BLOCK_LEN); + output.block_len = BLAKE3_BLOCK_LEN; + output.counter = 0; + output.d = (hash->chunk).d | PARENT; + blake3_output_chain(&output, parent_node); + hash->cv_stack_len -= 1; + } } -void blake3_hasher_push_cv(cx_blake3_t *hash, uint8_t *new_cv, - uint64_t chunk_counter) { - blake3_hasher_merge_cv(hash, chunk_counter); - memcpy(hash->cv_stack + hash->cv_stack_len * BLAKE3_OUT_LEN, new_cv, BLAKE3_OUT_LEN); - hash->cv_stack_len += 1; +void blake3_hasher_push_cv(cx_blake3_t *hash, uint8_t *new_cv, uint64_t chunk_counter) +{ + blake3_hasher_merge_cv(hash, chunk_counter); + memcpy(hash->cv_stack + hash->cv_stack_len * BLAKE3_OUT_LEN, new_cv, BLAKE3_OUT_LEN); + hash->cv_stack_len += 1; } -void blake3_output_root_bytes(const cx_blake3_state_out_t *chunk_out, uint8_t *out, - size_t out_len) { - uint64_t output_block_counter = 0; - size_t offset_within_block = 0; - uint8_t wide_buf[BLAKE3_BLOCK_LEN]; - - while (out_len > 0) { - blake3_compress_xof(chunk_out->input_cv, chunk_out->block, chunk_out->block_len, - output_block_counter, chunk_out->d | ROOT, wide_buf); - size_t available_bytes = BLAKE3_BLOCK_LEN - offset_within_block; - size_t memcpy_len; - if (out_len > available_bytes) { - memcpy_len = available_bytes; - } else { - memcpy_len = out_len; +void blake3_output_root_bytes(const cx_blake3_state_out_t *chunk_out, uint8_t *out, size_t out_len) +{ + uint64_t output_block_counter = 0; + size_t offset_within_block = 0; + uint8_t wide_buf[BLAKE3_BLOCK_LEN]; + + while (out_len > 0) { + blake3_compress_xof(chunk_out->input_cv, + chunk_out->block, + chunk_out->block_len, + output_block_counter, + chunk_out->d | ROOT, + wide_buf); + size_t available_bytes = BLAKE3_BLOCK_LEN - offset_within_block; + size_t memcpy_len; + if (out_len > available_bytes) { + memcpy_len = available_bytes; + } + else { + memcpy_len = out_len; + } + memcpy(out, wide_buf + offset_within_block, memcpy_len); + out += memcpy_len; + out_len -= memcpy_len; + output_block_counter += 1; + offset_within_block = 0; } - memcpy(out, wide_buf + offset_within_block, memcpy_len); - out += memcpy_len; - out_len -= memcpy_len; - output_block_counter += 1; - offset_within_block = 0; - } } -void blake3_init_ctx(cx_blake3_t *hash, const uint32_t *key, uint8_t mode) { - memcpy(hash->key, key, BLAKE3_KEY_LEN); - blake3_state_init(&hash->chunk, key, mode); - hash->cv_stack_len = 0; - hash->is_init = true; +void blake3_init_ctx(cx_blake3_t *hash, const uint32_t *key, uint8_t mode) +{ + memcpy(hash->key, key, BLAKE3_KEY_LEN); + blake3_state_init(&hash->chunk, key, mode); + hash->cv_stack_len = 0; + hash->is_init = true; } -#endif // HAVE_BLAKE3 +#endif // HAVE_BLAKE3 diff --git a/lib_cxng/src/cx_blake3_ref.h b/lib_cxng/src/cx_blake3_ref.h index b120d2406..4f30375e3 100644 --- a/lib_cxng/src/cx_blake3_ref.h +++ b/lib_cxng/src/cx_blake3_ref.h @@ -10,93 +10,100 @@ #define INLINE static inline __attribute__((always_inline)) -INLINE uint32_t load32(const void *src) { +INLINE uint32_t load32(const void *src) +{ #if defined(NATIVE_LITTLE_ENDIAN) - uint32_t w; - memcpy(&w, src, sizeof w); - return w; + uint32_t w; + memcpy(&w, src, sizeof w); + return w; #else - const uint8_t *p = (const uint8_t *)src; - return ((uint32_t)(p[0]) << 0) | ((uint32_t)(p[1]) << 8) | ((uint32_t)(p[2]) << 16) | ((uint32_t)(p[3]) << 24); + const uint8_t *p = (const uint8_t *) src; + return ((uint32_t) (p[0]) << 0) | ((uint32_t) (p[1]) << 8) | ((uint32_t) (p[2]) << 16) + | ((uint32_t) (p[3]) << 24); #endif } -INLINE uint32_t rotr32(uint32_t w, uint32_t c) { - return (w >> c) | (w << (32 - c)); +INLINE uint32_t rotr32(uint32_t w, uint32_t c) +{ + return (w >> c) | (w << (32 - c)); } -INLINE void load_key_words(const uint8_t key[BLAKE3_KEY_LEN], - uint32_t key_words[8]) { - key_words[0] = load32(&key[0 * 4]); - key_words[1] = load32(&key[1 * 4]); - key_words[2] = load32(&key[2 * 4]); - key_words[3] = load32(&key[3 * 4]); - key_words[4] = load32(&key[4 * 4]); - key_words[5] = load32(&key[5 * 4]); - key_words[6] = load32(&key[6 * 4]); - key_words[7] = load32(&key[7 * 4]); +INLINE void load_key_words(const uint8_t key[BLAKE3_KEY_LEN], uint32_t key_words[8]) +{ + key_words[0] = load32(&key[0 * 4]); + key_words[1] = load32(&key[1 * 4]); + key_words[2] = load32(&key[2 * 4]); + key_words[3] = load32(&key[3 * 4]); + key_words[4] = load32(&key[4 * 4]); + key_words[5] = load32(&key[5 * 4]); + key_words[6] = load32(&key[6 * 4]); + key_words[7] = load32(&key[7 * 4]); } -INLINE void store32(void *dst, uint32_t w) { +INLINE void store32(void *dst, uint32_t w) +{ #if defined(NATIVE_LITTLE_ENDIAN) - memcpy(dst, &w, sizeof w); + memcpy(dst, &w, sizeof w); #else - uint8_t *p = (uint8_t *)dst; - p[0] = (uint8_t)(w >> 0); - p[1] = (uint8_t)(w >> 8); - p[2] = (uint8_t)(w >> 16); - p[3] = (uint8_t)(w >> 24); + uint8_t *p = (uint8_t *) dst; + p[0] = (uint8_t) (w >> 0); + p[1] = (uint8_t) (w >> 8); + p[2] = (uint8_t) (w >> 16); + p[3] = (uint8_t) (w >> 24); #endif } -INLINE void store_cv_words(uint8_t bytes_out[32], uint32_t cv_words[8]) { - store32(&bytes_out[0 * 4], cv_words[0]); - store32(&bytes_out[1 * 4], cv_words[1]); - store32(&bytes_out[2 * 4], cv_words[2]); - store32(&bytes_out[3 * 4], cv_words[3]); - store32(&bytes_out[4 * 4], cv_words[4]); - store32(&bytes_out[5 * 4], cv_words[5]); - store32(&bytes_out[6 * 4], cv_words[6]); - store32(&bytes_out[7 * 4], cv_words[7]); +INLINE void store_cv_words(uint8_t bytes_out[32], uint32_t cv_words[8]) +{ + store32(&bytes_out[0 * 4], cv_words[0]); + store32(&bytes_out[1 * 4], cv_words[1]); + store32(&bytes_out[2 * 4], cv_words[2]); + store32(&bytes_out[3 * 4], cv_words[3]); + store32(&bytes_out[4 * 4], cv_words[4]); + store32(&bytes_out[5 * 4], cv_words[5]); + store32(&bytes_out[6 * 4], cv_words[6]); + store32(&bytes_out[7 * 4], cv_words[7]); } -static unsigned int highest_one(uint64_t x) { - unsigned int c = 0; - if (x & 0xffffffff00000000ULL) { - x >>= 32; - c += 32; - } - if (x & 0x00000000ffff0000ULL) { - x >>= 16; - c += 16; - } - if (x & 0x000000000000ff00ULL) { - x >>= 8; - c += 8; - } - if (x & 0x00000000000000f0ULL) { - x >>= 4; - c += 4; - } - if (x & 0x000000000000000cULL) { - x >>= 2; - c += 2; - } - if (x & 0x0000000000000002ULL) { - c += 1; - } - - return c; +static unsigned int highest_one(uint64_t x) +{ + unsigned int c = 0; + if (x & 0xffffffff00000000ULL) { + x >>= 32; + c += 32; + } + if (x & 0x00000000ffff0000ULL) { + x >>= 16; + c += 16; + } + if (x & 0x000000000000ff00ULL) { + x >>= 8; + c += 8; + } + if (x & 0x00000000000000f0ULL) { + x >>= 4; + c += 4; + } + if (x & 0x000000000000000cULL) { + x >>= 2; + c += 2; + } + if (x & 0x0000000000000002ULL) { + c += 1; + } + + return c; } // The Hamming weight of x, i.e. the number of 1 in the binary representation -INLINE unsigned int hw(uint64_t x) { - unsigned int count = 0; - while (x) { - count += 1; - x &= x - 1; - } - return count; +INLINE unsigned int hw(uint64_t x) +{ + unsigned int count = 0; + while (x) { + count += 1; + x &= x - 1; + } + return count; } /** @@ -133,7 +140,9 @@ void blake3_state_update(cx_blake3_state_t *chunk_state, const uint8_t *input, s * * @param[in] chunk_counter Number of already compressed chunks. */ -void blake3_state_reset(cx_blake3_state_t *chunk_state, const uint32_t *key, uint64_t chunk_counter); +void blake3_state_reset(cx_blake3_state_t *chunk_state, + const uint32_t *key, + uint64_t chunk_counter); /** * @brief Output the chunk state. @@ -181,8 +190,12 @@ void blake3_output_chain(const cx_blake3_state_out_t *out, uint8_t *cv); * * @param[out] out Output of the compression: the chaining value of a parent node. */ -void blake3_compress_subtree_to_parent(const uint8_t *input, size_t input_len, const uint32_t *key, - uint64_t chunk_counter, uint8_t flags, uint8_t *out); +void blake3_compress_subtree_to_parent(const uint8_t *input, + size_t input_len, + const uint32_t *key, + uint64_t chunk_counter, + uint8_t flags, + uint8_t *out); /** * @brief Merge the chaining values stack. @@ -230,5 +243,5 @@ void blake3_output_root_bytes(const cx_blake3_state_out_t *chunk_out, uint8_t *o */ void blake3_init_ctx(cx_blake3_t *hash, const uint32_t *key, uint8_t mode); -#endif // CX_BLAKE3_REF_H -#endif // HAVE_BLAKE3 +#endif // CX_BLAKE3_REF_H +#endif // HAVE_BLAKE3 diff --git a/lib_cxng/src/cx_chacha.c b/lib_cxng/src/cx_chacha.c index 48957dc47..9f1fad27a 100644 --- a/lib_cxng/src/cx_chacha.c +++ b/lib_cxng/src/cx_chacha.c @@ -1,20 +1,20 @@ /******************************************************************************* -* Ledger Nano S - Secure firmware -* (c) 2022 Ledger -* -* Licensed under the Apache License, Version 2.0 (the "License"); -* you may not use this file except in compliance with the License. -* You may obtain a copy of the License at -* -* http://www.apache.org/licenses/LICENSE-2.0 -* -* Unless required by applicable law or agreed to in writing, software -* distributed under the License is distributed on an "AS IS" BASIS, -* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -* See the License for the specific language governing permissions and -* limitations under the License. -********************************************************************************/ + * Ledger Nano S - Secure firmware + * (c) 2022 Ledger + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT 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(HAVE_CHACHA) @@ -36,166 +36,215 @@ static const uint8_t constants[16] = "expand 32-byte k"; /* Chacha-20 quarter round function */ -static void cx_chacha_quarter_round(uint32_t *a, uint32_t *b, uint32_t *c, uint32_t *d) { - *a = PLUS(*a, *b); *d = ROTATE(XOR(*d, *a), 16); - *c = PLUS(*c, *d); *b = ROTATE(XOR(*b, *c), 12); - *a = PLUS(*a, *b); *d = ROTATE(XOR(*d, *a), 8); - *c = PLUS(*c, *d); *b = ROTATE(XOR(*b, *c), 7); +static void cx_chacha_quarter_round(uint32_t *a, uint32_t *b, uint32_t *c, uint32_t *d) +{ + *a = PLUS(*a, *b); + *d = ROTATE(XOR(*d, *a), 16); + *c = PLUS(*c, *d); + *b = ROTATE(XOR(*b, *c), 12); + *a = PLUS(*a, *b); + *d = ROTATE(XOR(*d, *a), 8); + *c = PLUS(*c, *d); + *b = ROTATE(XOR(*b, *c), 7); } -static void cx_chacha_process_block(cx_chacha_context_t *ctx) { - unsigned int i; - uint32_t *x = (uint32_t *)ctx->block; - for (i = 0; i < CHACHA_STATE_ARRAY_SIZE; i++) { - x[i] = ctx->state[i]; - } - for (i = 0; i < ctx->nrounds; i += 2) { - /* Column rounds : apply the quarter-round function to each column */ - cx_chacha_quarter_round(&x[0], &x[4], &x[8], &x[12]); - cx_chacha_quarter_round(&x[1], &x[5], &x[9], &x[13]); - cx_chacha_quarter_round(&x[2], &x[6], &x[10], &x[14]); - cx_chacha_quarter_round(&x[3], &x[7], &x[11], &x[15]); - - /* Diagonal rounds : apply the quarter-round function to the 'diagonals' */ - cx_chacha_quarter_round(&x[0], &x[5], &x[10], &x[15]); - cx_chacha_quarter_round(&x[1], &x[6], &x[11], &x[12]); - cx_chacha_quarter_round(&x[2], &x[7], &x[8], &x[13]); - cx_chacha_quarter_round(&x[3], &x[4], &x[9], &x[14]); - } - for (i = 0; i < CHACHA_STATE_ARRAY_SIZE; i++) { - x[i] = PLUS(x[i], ctx->state[i]); - } +static void cx_chacha_process_block(cx_chacha_context_t *ctx) +{ + unsigned int i; + uint32_t *x = (uint32_t *) ctx->block; + for (i = 0; i < CHACHA_STATE_ARRAY_SIZE; i++) { + x[i] = ctx->state[i]; + } + for (i = 0; i < ctx->nrounds; i += 2) { + /* Column rounds : apply the quarter-round function to each column */ + cx_chacha_quarter_round(&x[0], &x[4], &x[8], &x[12]); + cx_chacha_quarter_round(&x[1], &x[5], &x[9], &x[13]); + cx_chacha_quarter_round(&x[2], &x[6], &x[10], &x[14]); + cx_chacha_quarter_round(&x[3], &x[7], &x[11], &x[15]); + + /* Diagonal rounds : apply the quarter-round function to the 'diagonals' */ + cx_chacha_quarter_round(&x[0], &x[5], &x[10], &x[15]); + cx_chacha_quarter_round(&x[1], &x[6], &x[11], &x[12]); + cx_chacha_quarter_round(&x[2], &x[7], &x[8], &x[13]); + cx_chacha_quarter_round(&x[3], &x[4], &x[9], &x[14]); + } + for (i = 0; i < CHACHA_STATE_ARRAY_SIZE; i++) { + x[i] = PLUS(x[i], ctx->state[i]); + } } -void cx_chacha_init(cx_chacha_context_t *ctx, uint32_t nrounds) { - memset(ctx, 0, sizeof(cx_chacha_context_t)); - ctx->nrounds = nrounds; +void cx_chacha_init(cx_chacha_context_t *ctx, uint32_t nrounds) +{ + memset(ctx, 0, sizeof(cx_chacha_context_t)); + ctx->nrounds = nrounds; } -cx_err_t cx_chacha_set_key(cx_chacha_context_t *ctx, const uint8_t *key, size_t key_len) { - if (key_len != 32) { - return CX_INVALID_PARAMETER_VALUE; - } - - /* Initialize the state array */ - ctx->state[4] = U4LE(key, 0); - ctx->state[5] = U4LE(key, 4); - ctx->state[6] = U4LE(key, 8); - ctx->state[7] = U4LE(key, 12); - ctx->state[8] = U4LE(key, 16); - ctx->state[9] = U4LE(key, 20); - ctx->state[10] = U4LE(key, 24); - ctx->state[11] = U4LE(key, 28); - - ctx->state[0] = U4LE(constants, 0); - ctx->state[1] = U4LE(constants, 4); - ctx->state[2] = U4LE(constants, 8); - ctx->state[3] = U4LE(constants, 12); - - return CX_OK; -} +cx_err_t cx_chacha_set_key(cx_chacha_context_t *ctx, const uint8_t *key, size_t key_len) +{ + if (key_len != 32) { + return CX_INVALID_PARAMETER_VALUE; + } -cx_err_t cx_chacha_start(cx_chacha_context_t *ctx, const uint8_t *iv, size_t iv_len) { - if (iv_len != 16) { - return CX_INVALID_PARAMETER_VALUE; - } - /* Set the counter value */ - ctx->state[12] = U4BE(iv, 0); - /* Set the nonce value */ - ctx->state[13] = U4LE(iv, 4); - ctx->state[14] = U4LE(iv, 8); - ctx->state[15] = U4LE(iv, 12); - ctx-> pos = 0; - - return CX_OK; + /* Initialize the state array */ + ctx->state[4] = U4LE(key, 0); + ctx->state[5] = U4LE(key, 4); + ctx->state[6] = U4LE(key, 8); + ctx->state[7] = U4LE(key, 12); + ctx->state[8] = U4LE(key, 16); + ctx->state[9] = U4LE(key, 20); + ctx->state[10] = U4LE(key, 24); + ctx->state[11] = U4LE(key, 28); + + ctx->state[0] = U4LE(constants, 0); + ctx->state[1] = U4LE(constants, 4); + ctx->state[2] = U4LE(constants, 8); + ctx->state[3] = U4LE(constants, 12); + + return CX_OK; } -cx_err_t cx_chacha_update(cx_chacha_context_t *ctx, const uint8_t *input, uint8_t *output, size_t len) { - unsigned int i, n; - uint8_t *key_stream; - - while (len > 0) { - if ((0 == ctx->pos) || (ctx->pos >= 64)) { - cx_chacha_process_block(ctx); - ctx->state[12]++; - if (0 == ctx->state[12]) { - ctx->state[13]++; - } - ctx->pos = 0; +cx_err_t cx_chacha_start(cx_chacha_context_t *ctx, const uint8_t *iv, size_t iv_len) +{ + if (iv_len != 16) { + return CX_INVALID_PARAMETER_VALUE; } - n = MIN(len, CHACHA_BLOCK_SIZE - ctx->pos); - key_stream = (uint8_t *) ctx->block + ctx->pos; - if (NULL == input) { - for (i = 0; i < n; i++) { - output[i] = key_stream[i]; - } - } - else { - for (i = 0; i < n; i++) { - output[i] = input[i] ^ key_stream[i]; - } + /* Set the counter value */ + ctx->state[12] = U4BE(iv, 0); + /* Set the nonce value */ + ctx->state[13] = U4LE(iv, 4); + ctx->state[14] = U4LE(iv, 8); + ctx->state[15] = U4LE(iv, 12); + ctx->pos = 0; + + return CX_OK; +} + +cx_err_t cx_chacha_update(cx_chacha_context_t *ctx, + const uint8_t *input, + uint8_t *output, + size_t len) +{ + unsigned int i, n; + uint8_t *key_stream; + + while (len > 0) { + if ((0 == ctx->pos) || (ctx->pos >= 64)) { + cx_chacha_process_block(ctx); + ctx->state[12]++; + if (0 == ctx->state[12]) { + ctx->state[13]++; + } + ctx->pos = 0; + } + n = MIN(len, CHACHA_BLOCK_SIZE - ctx->pos); + key_stream = (uint8_t *) ctx->block + ctx->pos; + if (NULL == input) { + for (i = 0; i < n; i++) { + output[i] = key_stream[i]; + } + } + else { + for (i = 0; i < n; i++) { + output[i] = input[i] ^ key_stream[i]; + } + } + input += n; + output += n; + ctx->pos += n; + len -= n; } - input += n; - output += n; - ctx->pos += n; - len -= n; - } - return CX_OK; + return CX_OK; } -cx_err_t cx_chacha_cipher(uint32_t nrounds, - const uint8_t *key, size_t key_len, - const uint8_t *iv, size_t iv_len, +cx_err_t cx_chacha_cipher(uint32_t nrounds, + const uint8_t *key, + size_t key_len, + const uint8_t *iv, + size_t iv_len, const uint8_t *input, - uint8_t *output, size_t len) { - cx_chacha_context_t *ctx = &G_cx.chacha; - cx_err_t error; - cx_chacha_init(ctx, nrounds); - CX_CHECK(cx_chacha_set_key(ctx, key, key_len)); - CX_CHECK(cx_chacha_start(ctx, iv, iv_len)); - CX_CHECK(cx_chacha_update(ctx, input, output, len)); - - end: - explicit_bzero(ctx, sizeof(cx_chacha_context_t)); - return error; + uint8_t *output, + size_t len) +{ + cx_chacha_context_t *ctx = &G_cx.chacha; + cx_err_t error; + cx_chacha_init(ctx, nrounds); + CX_CHECK(cx_chacha_set_key(ctx, key, key_len)); + CX_CHECK(cx_chacha_start(ctx, iv, iv_len)); + CX_CHECK(cx_chacha_update(ctx, input, output, len)); + +end: + explicit_bzero(ctx, sizeof(cx_chacha_context_t)); + return error; } -#endif // HAVE_CHACHA +#endif // HAVE_CHACHA #ifdef UNIT_TESTING #include #include -static void test_chacha_round(void **state) { - (void) state; - - uint32_t state_array[16] = {0x61707865, 0x3320646e, 0x79622d32, 0x6b206574, - 0x03020100, 0x07060504, 0x0b0a0908, 0x0f0e0d0c, - 0x13121110, 0x17161514, 0x1b1a1918, 0x1f1e1d1c, - 0x00000001, 0x09000000, 0x4a000000, 0x00000000}; - uint32_t expected_array[16] = {0x837778ab, 0xe238d763, 0xa67ae21e, 0x5950bb2f, - 0xc4f2d0c7, 0xfc62bb2f, 0x8fa018fc, 0x3f5ec7b7, - 0x335271c2, 0xf29489f3, 0xeabda8fc, 0x82e46ebd, - 0xd19c12b4, 0xb04e16de, 0x9e83d0cb, 0x4e3c50a2}; - for (int i = 0; i < 10; i++) { - cx_chacha_quarter_round(&state_array[0], &state_array[4], &state_array[8], &state_array[12]); - cx_chacha_quarter_round(&state_array[1], &state_array[5], &state_array[9], &state_array[13]); - cx_chacha_quarter_round(&state_array[2], &state_array[6], &state_array[10], &state_array[14]); - cx_chacha_quarter_round(&state_array[3], &state_array[7], &state_array[11], &state_array[15]); - - cx_chacha_quarter_round(&state_array[0], &state_array[5], &state_array[10], &state_array[15]); - cx_chacha_quarter_round(&state_array[1], &state_array[6], &state_array[11], &state_array[12]); - cx_chacha_quarter_round(&state_array[2], &state_array[7], &state_array[8], &state_array[13]); - cx_chacha_quarter_round(&state_array[3], &state_array[4], &state_array[9], &state_array[14]); - } - - assert_memory_equal(state_array, expected_array, sizeof(state_array)); +static void test_chacha_round(void **state) +{ + (void) state; + + uint32_t state_array[16] = {0x61707865, + 0x3320646e, + 0x79622d32, + 0x6b206574, + 0x03020100, + 0x07060504, + 0x0b0a0908, + 0x0f0e0d0c, + 0x13121110, + 0x17161514, + 0x1b1a1918, + 0x1f1e1d1c, + 0x00000001, + 0x09000000, + 0x4a000000, + 0x00000000}; + uint32_t expected_array[16] = {0x837778ab, + 0xe238d763, + 0xa67ae21e, + 0x5950bb2f, + 0xc4f2d0c7, + 0xfc62bb2f, + 0x8fa018fc, + 0x3f5ec7b7, + 0x335271c2, + 0xf29489f3, + 0xeabda8fc, + 0x82e46ebd, + 0xd19c12b4, + 0xb04e16de, + 0x9e83d0cb, + 0x4e3c50a2}; + for (int i = 0; i < 10; i++) { + cx_chacha_quarter_round( + &state_array[0], &state_array[4], &state_array[8], &state_array[12]); + cx_chacha_quarter_round( + &state_array[1], &state_array[5], &state_array[9], &state_array[13]); + cx_chacha_quarter_round( + &state_array[2], &state_array[6], &state_array[10], &state_array[14]); + cx_chacha_quarter_round( + &state_array[3], &state_array[7], &state_array[11], &state_array[15]); + + cx_chacha_quarter_round( + &state_array[0], &state_array[5], &state_array[10], &state_array[15]); + cx_chacha_quarter_round( + &state_array[1], &state_array[6], &state_array[11], &state_array[12]); + cx_chacha_quarter_round( + &state_array[2], &state_array[7], &state_array[8], &state_array[13]); + cx_chacha_quarter_round( + &state_array[3], &state_array[4], &state_array[9], &state_array[14]); + } + + assert_memory_equal(state_array, expected_array, sizeof(state_array)); } -int main(void) { - const struct CMUnitTest tests[] = { - cmocka_unit_test(test_chacha_round) - }; +int main(void) +{ + const struct CMUnitTest tests[] = {cmocka_unit_test(test_chacha_round)}; - return cmocka_run_group_tests(tests, NULL, NULL); + return cmocka_run_group_tests(tests, NULL, NULL); } -#endif // UNIT_TESTING +#endif // UNIT_TESTING diff --git a/lib_cxng/src/cx_chacha_poly.c b/lib_cxng/src/cx_chacha_poly.c index 3df81d7c3..f295d2701 100644 --- a/lib_cxng/src/cx_chacha_poly.c +++ b/lib_cxng/src/cx_chacha_poly.c @@ -1,20 +1,20 @@ /******************************************************************************* -* Ledger Nano S - Secure firmware -* (c) 2022 Ledger -* -* Licensed under the Apache License, Version 2.0 (the "License"); -* you may not use this file except in compliance with the License. -* You may obtain a copy of the License at -* -* http://www.apache.org/licenses/LICENSE-2.0 -* -* Unless required by applicable law or agreed to in writing, software -* distributed under the License is distributed on an "AS IS" BASIS, -* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -* See the License for the specific language governing permissions and -* limitations under the License. -********************************************************************************/ + * Ledger Nano S - Secure firmware + * (c) 2022 Ledger + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT 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(HAVE_CHACHA_POLY) #if defined(HAVE_CHACHA) && defined(HAVE_POLY1305) #include "cx_chacha_poly.h" @@ -33,218 +33,245 @@ #if defined(HAVE_AEAD) static const cx_aead_base_t cx_chachapoly_functions = { - (void (*) (void *ctx))cx_chachapoly_init, - (cx_err_t (*) (void *ctx, const uint8_t *key, size_t key_len))cx_chachapoly_set_key, - (cx_err_t(*) (void *ctx, uint32_t mode, const uint8_t *iv, size_t iv_len))cx_chachapoly_start, - (cx_err_t(*) (void *ctx, const uint8_t *aad, size_t aad_len))cx_chachapoly_update_aad, - (cx_err_t(*) (void *ctx, const uint8_t *input, uint8_t *output, size_t len))cx_chachapoly_update, - (cx_err_t(*) (void *ctx, uint8_t *tag, size_t tag_len))cx_chachapoly_finish, - (cx_err_t(*) (void *ctx, const uint8_t *input, size_t len, - const uint8_t *iv, size_t iv_len, - const uint8_t *aad, size_t aad_len, - uint8_t *output, uint8_t *tag, size_t tag_len))cx_chachapoly_encrypt_and_tag, - (cx_err_t(*) (void *ctx, const uint8_t *input, size_t len, - const uint8_t *iv, size_t iv_len, - const uint8_t *aad, size_t aad_len, - uint8_t *output, const uint8_t *tag, size_t tag_len))cx_chachapoly_decrypt_and_auth, - (cx_err_t(*) (void *ctx, const uint8_t *tag, size_t tag_len))cx_chachapoly_check_tag -}; - -const cx_aead_info_t cx_chacha20_poly1305_info = { - CX_AEAD_CHACHA20_POLY1305, - 256, - 512, - &cx_chachapoly_functions -}; -#endif // HAVE_AEAD - -void cx_chachapoly_init(cx_chachapoly_context_t *ctx) { - - cx_chacha_init(&ctx->chacha20_ctx, CHACHAPOLY_N_ROUNDS); - cx_poly1305_init(&ctx->poly1305_ctx); - ctx->aad_len = 0; - ctx->ciphertext_len = 0; - ctx->state = CHACHAPOLY_STATE_INIT; - ctx->mode = CX_ENCRYPT; + (void (*)(void *ctx)) cx_chachapoly_init, + (cx_err_t(*)(void *ctx, const uint8_t *key, size_t key_len)) cx_chachapoly_set_key, + (cx_err_t(*)(void *ctx, uint32_t mode, const uint8_t *iv, size_t iv_len)) cx_chachapoly_start, + (cx_err_t(*)(void *ctx, const uint8_t *aad, size_t aad_len)) cx_chachapoly_update_aad, + (cx_err_t(*)(void *ctx, const uint8_t *input, uint8_t *output, size_t len)) + cx_chachapoly_update, + (cx_err_t(*)(void *ctx, uint8_t *tag, size_t tag_len)) cx_chachapoly_finish, + (cx_err_t(*)(void *ctx, + const uint8_t *input, + size_t len, + const uint8_t *iv, + size_t iv_len, + const uint8_t *aad, + size_t aad_len, + uint8_t *output, + uint8_t *tag, + size_t tag_len)) cx_chachapoly_encrypt_and_tag, + (cx_err_t(*)(void *ctx, + const uint8_t *input, + size_t len, + const uint8_t *iv, + size_t iv_len, + const uint8_t *aad, + size_t aad_len, + uint8_t *output, + const uint8_t *tag, + size_t tag_len)) cx_chachapoly_decrypt_and_auth, + (cx_err_t(*)(void *ctx, const uint8_t *tag, size_t tag_len)) cx_chachapoly_check_tag}; + +const cx_aead_info_t cx_chacha20_poly1305_info + = {CX_AEAD_CHACHA20_POLY1305, 256, 512, &cx_chachapoly_functions}; +#endif // HAVE_AEAD + +void cx_chachapoly_init(cx_chachapoly_context_t *ctx) +{ + cx_chacha_init(&ctx->chacha20_ctx, CHACHAPOLY_N_ROUNDS); + cx_poly1305_init(&ctx->poly1305_ctx); + ctx->aad_len = 0; + ctx->ciphertext_len = 0; + ctx->state = CHACHAPOLY_STATE_INIT; + ctx->mode = CX_ENCRYPT; } -cx_err_t cx_chachapoly_set_key(cx_chachapoly_context_t *ctx, - const uint8_t *key, size_t key_len) { - - return cx_chacha_set_key(&ctx->chacha20_ctx, key, key_len); +cx_err_t cx_chachapoly_set_key(cx_chachapoly_context_t *ctx, const uint8_t *key, size_t key_len) +{ + return cx_chacha_set_key(&ctx->chacha20_ctx, key, key_len); } -cx_err_t cx_chachapoly_start(cx_chachapoly_context_t *ctx, uint32_t mode, - const uint8_t *iv, size_t iv_len) { - cx_err_t error; - uint8_t poly1305_key[64]; - - /* iv = 0 || nonce */ - CX_CHECK(cx_chacha_start( &ctx->chacha20_ctx, iv, iv_len)); - - /* 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)); - CX_CHECK(cx_chacha_update(&ctx->chacha20_ctx, poly1305_key, - poly1305_key, sizeof(poly1305_key))); - - cx_poly1305_set_key(&ctx->poly1305_ctx, poly1305_key); - ctx->aad_len = 0; - ctx->ciphertext_len = 0; - ctx->state = CHACHAPOLY_STATE_AAD; - ctx->mode = mode; - - end: - memset(poly1305_key, 0, 64); - return error; +cx_err_t cx_chachapoly_start(cx_chachapoly_context_t *ctx, + uint32_t mode, + const uint8_t *iv, + size_t iv_len) +{ + cx_err_t error; + uint8_t poly1305_key[64]; + + /* iv = 0 || nonce */ + CX_CHECK(cx_chacha_start(&ctx->chacha20_ctx, iv, iv_len)); + + /* 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)); + CX_CHECK( + cx_chacha_update(&ctx->chacha20_ctx, poly1305_key, poly1305_key, sizeof(poly1305_key))); + + cx_poly1305_set_key(&ctx->poly1305_ctx, poly1305_key); + ctx->aad_len = 0; + ctx->ciphertext_len = 0; + ctx->state = CHACHAPOLY_STATE_AAD; + ctx->mode = mode; + +end: + memset(poly1305_key, 0, 64); + return error; } -cx_err_t cx_chachapoly_update_aad(cx_chachapoly_context_t *ctx, - const uint8_t *aad, - size_t aad_len) { - - if (ctx->state != CHACHAPOLY_STATE_AAD) { - return CX_INTERNAL_ERROR; - } +cx_err_t cx_chachapoly_update_aad(cx_chachapoly_context_t *ctx, const uint8_t *aad, size_t aad_len) +{ + if (ctx->state != CHACHAPOLY_STATE_AAD) { + return CX_INTERNAL_ERROR; + } - ctx->aad_len += aad_len; - return cx_poly1305_update(&ctx->poly1305_ctx, aad, aad_len); + ctx->aad_len += aad_len; + return cx_poly1305_update(&ctx->poly1305_ctx, aad, aad_len); } -static cx_err_t cx_chachapoly_pad(cx_chachapoly_context_t *ctx, size_t in_to_pad_len) { +static cx_err_t cx_chachapoly_pad(cx_chachapoly_context_t *ctx, size_t in_to_pad_len) +{ uint32_t pad_len = in_to_pad_len % 16; unsigned char pad_bytes[15]; if (!pad_len) { - return CX_OK; + return CX_OK; } memset(pad_bytes, 0, sizeof(pad_bytes)); - return cx_poly1305_update(&ctx->poly1305_ctx, pad_bytes, - 16 - pad_len); + return cx_poly1305_update(&ctx->poly1305_ctx, pad_bytes, 16 - pad_len); } cx_err_t cx_chachapoly_update(cx_chachapoly_context_t *ctx, - const uint8_t *input, - uint8_t *output, size_t len) { - cx_err_t error; - - if ((ctx->state != CHACHAPOLY_STATE_AAD) && - (ctx->state != CHACHAPOLY_STATE_CIPHERTEXT)) { - return CX_INTERNAL_ERROR; - } - if (CHACHAPOLY_STATE_AAD == ctx->state) { - ctx->state = CHACHAPOLY_STATE_CIPHERTEXT; - CX_CHECK(cx_chachapoly_pad(ctx, ctx->aad_len)); - } - ctx->ciphertext_len += len; - if (CX_ENCRYPT == ctx->mode) { - CX_CHECK(cx_chacha_update(&ctx->chacha20_ctx, input, output, len)); - CX_CHECK(cx_poly1305_update(&ctx->poly1305_ctx, output, len)); - } - else { /* DECRYPT */ - CX_CHECK(cx_poly1305_update(&ctx->poly1305_ctx, input, len)); - CX_CHECK(cx_chacha_update(&ctx->chacha20_ctx, input, output, len)); - } - end: - return error; + const uint8_t *input, + uint8_t *output, + size_t len) +{ + cx_err_t error; + + if ((ctx->state != CHACHAPOLY_STATE_AAD) && (ctx->state != CHACHAPOLY_STATE_CIPHERTEXT)) { + return CX_INTERNAL_ERROR; + } + if (CHACHAPOLY_STATE_AAD == ctx->state) { + ctx->state = CHACHAPOLY_STATE_CIPHERTEXT; + CX_CHECK(cx_chachapoly_pad(ctx, ctx->aad_len)); + } + ctx->ciphertext_len += len; + if (CX_ENCRYPT == ctx->mode) { + CX_CHECK(cx_chacha_update(&ctx->chacha20_ctx, input, output, len)); + CX_CHECK(cx_poly1305_update(&ctx->poly1305_ctx, output, len)); + } + else { /* DECRYPT */ + CX_CHECK(cx_poly1305_update(&ctx->poly1305_ctx, input, len)); + CX_CHECK(cx_chacha_update(&ctx->chacha20_ctx, input, output, len)); + } +end: + return error; } -cx_err_t cx_chachapoly_finish(cx_chachapoly_context_t *ctx, - uint8_t *tag, size_t tag_len) { - cx_err_t error; - uint8_t len_block[16]; - - if (tag_len != CHACHAPOLY_TAG_LEN) { - return CX_INVALID_PARAMETER_VALUE; - } - - if (CHACHAPOLY_STATE_INIT == ctx->state) { - return CX_INTERNAL_ERROR; - } - if (CHACHAPOLY_STATE_AAD == ctx->state) { - CX_CHECK(cx_chachapoly_pad(ctx, ctx->aad_len)); - } - else if (CHACHAPOLY_STATE_CIPHERTEXT == ctx->state) { - CX_CHECK(cx_chachapoly_pad(ctx, ctx->ciphertext_len)); - } - 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. - */ - memset(len_block, 0, 16); - U4LE_ENCODE(len_block, 0, ctx->aad_len); - U4LE_ENCODE(len_block, 8, ctx->ciphertext_len); - CX_CHECK(cx_poly1305_update(&ctx->poly1305_ctx, len_block, 16)); - CX_CHECK(cx_poly1305_finish(&ctx->poly1305_ctx, tag)); - - end: - return error; +cx_err_t cx_chachapoly_finish(cx_chachapoly_context_t *ctx, uint8_t *tag, size_t tag_len) +{ + cx_err_t error; + uint8_t len_block[16]; + + if (tag_len != CHACHAPOLY_TAG_LEN) { + return CX_INVALID_PARAMETER_VALUE; + } + + if (CHACHAPOLY_STATE_INIT == ctx->state) { + return CX_INTERNAL_ERROR; + } + if (CHACHAPOLY_STATE_AAD == ctx->state) { + CX_CHECK(cx_chachapoly_pad(ctx, ctx->aad_len)); + } + else if (CHACHAPOLY_STATE_CIPHERTEXT == ctx->state) { + CX_CHECK(cx_chachapoly_pad(ctx, ctx->ciphertext_len)); + } + 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. + */ + memset(len_block, 0, 16); + U4LE_ENCODE(len_block, 0, ctx->aad_len); + U4LE_ENCODE(len_block, 8, ctx->ciphertext_len); + CX_CHECK(cx_poly1305_update(&ctx->poly1305_ctx, len_block, 16)); + CX_CHECK(cx_poly1305_finish(&ctx->poly1305_ctx, tag)); + +end: + return error; } -static cx_err_t cx_chachapoly_process_and_tag(cx_chachapoly_context_t *ctx, uint32_t mode, - const uint8_t *input, size_t len, - const uint8_t *iv, size_t iv_len, - const uint8_t *aad, size_t aad_len, - uint8_t *output, uint8_t *tag, size_t tag_len) { - cx_err_t error; - CX_CHECK(cx_chachapoly_start(ctx, mode, iv, iv_len)); - CX_CHECK(cx_chachapoly_update_aad(ctx, aad, aad_len)); - CX_CHECK(cx_chachapoly_update(ctx, input, output, len)); - CX_CHECK(cx_chachapoly_finish(ctx, tag, tag_len)); - end: - return error; +static cx_err_t cx_chachapoly_process_and_tag(cx_chachapoly_context_t *ctx, + uint32_t mode, + const uint8_t *input, + size_t len, + const uint8_t *iv, + size_t iv_len, + const uint8_t *aad, + size_t aad_len, + uint8_t *output, + uint8_t *tag, + size_t tag_len) +{ + cx_err_t error; + CX_CHECK(cx_chachapoly_start(ctx, mode, iv, iv_len)); + CX_CHECK(cx_chachapoly_update_aad(ctx, aad, aad_len)); + CX_CHECK(cx_chachapoly_update(ctx, input, output, len)); + CX_CHECK(cx_chachapoly_finish(ctx, tag, tag_len)); +end: + return error; } cx_err_t cx_chachapoly_encrypt_and_tag(cx_chachapoly_context_t *ctx, - const uint8_t *input, size_t len, - const uint8_t *iv, size_t iv_len, - const uint8_t *aad, size_t aad_len, - uint8_t *output, uint8_t *tag, size_t tag_len) { - return cx_chachapoly_process_and_tag(ctx, CX_ENCRYPT, input, len, - iv, iv_len, aad, aad_len, - output, tag, tag_len); + const uint8_t *input, + size_t len, + const uint8_t *iv, + size_t iv_len, + const uint8_t *aad, + size_t aad_len, + uint8_t *output, + uint8_t *tag, + size_t tag_len) +{ + return cx_chachapoly_process_and_tag( + ctx, CX_ENCRYPT, input, len, iv, iv_len, aad, aad_len, output, tag, tag_len); } cx_err_t cx_chachapoly_decrypt_and_auth(cx_chachapoly_context_t *ctx, - const uint8_t *input, size_t len, - const uint8_t *iv, size_t iv_len, - const uint8_t *aad, size_t aad_len, - uint8_t *output, const uint8_t *tag, size_t tag_len) { - uint8_t check_tag[CHACHAPOLY_TAG_LEN]; - uint8_t diff; - cx_err_t error; - - memset(check_tag, 0, CHACHAPOLY_TAG_LEN); - CX_CHECK(cx_chachapoly_process_and_tag(ctx, CX_DECRYPT, input, len, - iv, iv_len, aad, aad_len, - output, check_tag, tag_len)); - - diff = cx_constant_time_eq(tag, check_tag, CHACHAPOLY_TAG_LEN); - error = ((diff == 0) ? CX_OK : CX_INVALID_PARAMETER_VALUE); - if (error) { + const uint8_t *input, + size_t len, + const uint8_t *iv, + size_t iv_len, + const uint8_t *aad, + size_t aad_len, + uint8_t *output, + const uint8_t *tag, + size_t tag_len) +{ + uint8_t check_tag[CHACHAPOLY_TAG_LEN]; + uint8_t diff; + cx_err_t error; + memset(check_tag, 0, CHACHAPOLY_TAG_LEN); - } + CX_CHECK(cx_chachapoly_process_and_tag( + ctx, CX_DECRYPT, input, len, iv, iv_len, aad, aad_len, output, check_tag, tag_len)); - end: - return error; + diff = cx_constant_time_eq(tag, check_tag, CHACHAPOLY_TAG_LEN); + error = ((diff == 0) ? CX_OK : CX_INVALID_PARAMETER_VALUE); + if (error) { + memset(check_tag, 0, CHACHAPOLY_TAG_LEN); + } + +end: + return error; } -cx_err_t cx_chachapoly_check_tag(cx_chachapoly_context_t *ctx, const uint8_t *tag, size_t tag_len) { - cx_err_t error; - uint8_t diff; - uint8_t check_tag[CHACHAPOLY_TAG_LEN]; +cx_err_t cx_chachapoly_check_tag(cx_chachapoly_context_t *ctx, const uint8_t *tag, size_t tag_len) +{ + cx_err_t error; + uint8_t diff; + uint8_t check_tag[CHACHAPOLY_TAG_LEN]; - CX_CHECK(cx_chachapoly_finish(ctx, check_tag, tag_len)); + CX_CHECK(cx_chachapoly_finish(ctx, check_tag, tag_len)); - diff = cx_constant_time_eq(tag, check_tag, tag_len); - error = diff * CX_INVALID_PARAMETER_VALUE + (1 - diff) * CX_OK; - end: + diff = cx_constant_time_eq(tag, check_tag, tag_len); + error = diff * CX_INVALID_PARAMETER_VALUE + (1 - diff) * CX_OK; +end: return error; } -#endif // HAVE_CHACHA && HAVE_POLY1305 -#endif // HAVE_CHACHA_POLY +#endif // HAVE_CHACHA && HAVE_POLY1305 +#endif // HAVE_CHACHA_POLY diff --git a/lib_cxng/src/cx_chacha_poly.h b/lib_cxng/src/cx_chacha_poly.h index b816b73a9..a2f61c033 100644 --- a/lib_cxng/src/cx_chacha_poly.h +++ b/lib_cxng/src/cx_chacha_poly.h @@ -1,20 +1,20 @@ /******************************************************************************* -* Ledger Nano S - Secure firmware -* (c) 2022 Ledger -* -* Licensed under the Apache License, Version 2.0 (the "License"); -* you may not use this file except in compliance with the License. -* You may obtain a copy of the License at -* -* http://www.apache.org/licenses/LICENSE-2.0 -* -* Unless required by applicable law or agreed to in writing, software -* distributed under the License is distributed on an "AS IS" BASIS, -* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -* See the License for the specific language governing permissions and -* limitations under the License. -********************************************************************************/ + * Ledger Nano S - Secure firmware + * (c) 2022 Ledger + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT 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(HAVE_CHACHA_POLY) #if defined(HAVE_POLY1305) && defined(HAVE_CHACHA) @@ -23,7 +23,7 @@ #if defined(HAVE_AEAD) #include "lcx_aead.h" -#endif // HAVE_AEAD +#endif // HAVE_AEAD #include "lcx_chacha.h" #include "lcx_chacha_poly.h" #include "cx_poly1305.h" @@ -32,8 +32,8 @@ #if defined(HAVE_AEAD) extern const cx_aead_info_t cx_chacha20_poly1305_info; -#endif // HAVE_AEAD +#endif // HAVE_AEAD -#endif /* CX_CHACHA_POLY_H */ -#endif // HAVE_POLY1305 && HAVE_CHACHA -#endif // HAVE_CHACHA_POLY +#endif /* CX_CHACHA_POLY_H */ +#endif // HAVE_POLY1305 && HAVE_CHACHA +#endif // HAVE_CHACHA_POLY diff --git a/lib_cxng/src/cx_cipher.c b/lib_cxng/src/cx_cipher.c index 2d59005f3..0e50e7ff3 100644 --- a/lib_cxng/src/cx_cipher.c +++ b/lib_cxng/src/cx_cipher.c @@ -9,239 +9,263 @@ #define CX_MAX_BLOCK_SIZE 16 -static cx_err_t cx_cipher_check_out_len(cx_cipher_context_t *ctx, - size_t in_len, size_t out_len) { - - if (CX_CHAIN_CTR == ctx->mode) { - if (out_len < in_len) { - return CX_INVALID_PARAMETER; +static cx_err_t cx_cipher_check_out_len(cx_cipher_context_t *ctx, size_t in_len, size_t out_len) +{ + if (CX_CHAIN_CTR == ctx->mode) { + if (out_len < in_len) { + return CX_INVALID_PARAMETER; + } + return CX_OK; } - return CX_OK; - } - if ((CX_SIGN == ctx->operation) || (CX_VERIFY == ctx->operation)) { - if (out_len < 8) { - return CX_INVALID_PARAMETER; - } - } else if (CX_DECRYPT == ctx->operation) { - if (out_len < in_len) { - return CX_INVALID_PARAMETER; - } - } else if (CX_ENCRYPT == ctx->operation) { - if (NULL == ctx->add_padding) { - if (out_len < UPPER_ALIGN(in_len, 8, size_t)) { - return CX_INVALID_PARAMETER; - } - } else { - if (out_len < UPPER_ALIGN(in_len + 7, 8, size_t)) { - return CX_INVALID_PARAMETER; - } + if ((CX_SIGN == ctx->operation) || (CX_VERIFY == ctx->operation)) { + if (out_len < 8) { + return CX_INVALID_PARAMETER; + } } - } - return CX_OK; + else if (CX_DECRYPT == ctx->operation) { + if (out_len < in_len) { + return CX_INVALID_PARAMETER; + } + } + else if (CX_ENCRYPT == ctx->operation) { + if (NULL == ctx->add_padding) { + if (out_len < UPPER_ALIGN(in_len, 8, size_t)) { + return CX_INVALID_PARAMETER; + } + } + else { + if (out_len < UPPER_ALIGN(in_len + 7, 8, size_t)) { + return CX_INVALID_PARAMETER; + } + } + } + return CX_OK; } -static const cx_cipher_info_t *cx_cipher_get_info(const cx_cipher_id_t type) { - switch (type) { +static const cx_cipher_info_t *cx_cipher_get_info(const cx_cipher_id_t type) +{ + switch (type) { #ifdef HAVE_AES - case CX_CIPHER_AES_128: - return &cx_aes_128_info; - case CX_CIPHER_AES_192: - return &cx_aes_192_info; - case CX_CIPHER_AES_256: - return &cx_aes_256_info; -#endif // HAVE_AES - default: - return NULL; - } - + case CX_CIPHER_AES_128: + return &cx_aes_128_info; + case CX_CIPHER_AES_192: + return &cx_aes_192_info; + case CX_CIPHER_AES_256: + return &cx_aes_256_info; +#endif // HAVE_AES + default: + return NULL; + } } -static cx_err_t get_no_padding(uint8_t *input, size_t in_len, size_t *data_len) { - if ((NULL == input) || (NULL == data_len)) { - return CX_INVALID_PARAMETER; - } - *data_len = in_len; - return CX_OK; +static cx_err_t get_no_padding(uint8_t *input, size_t in_len, size_t *data_len) +{ + if ((NULL == input) || (NULL == data_len)) { + return CX_INVALID_PARAMETER; + } + *data_len = in_len; + return CX_OK; } -static void add_zeros_padding(uint8_t *output, size_t out_len, size_t data_len) { - size_t i; +static void add_zeros_padding(uint8_t *output, size_t out_len, size_t data_len) +{ + size_t i; - for (i = data_len; i < out_len; i++) { - output[i] = 0x00; - } + for (i = data_len; i < out_len; i++) { + output[i] = 0x00; + } } -void add_one_and_zeros_padding(uint8_t *output, size_t out_len, size_t data_len) { - size_t padding_len = out_len - data_len; - size_t i = 0; +void add_one_and_zeros_padding(uint8_t *output, size_t out_len, size_t data_len) +{ + size_t padding_len = out_len - data_len; + size_t i = 0; - output[data_len] = 0x80; - for (i = 1; i < padding_len; i++) { - output[data_len + i] = 0x00; - } + output[data_len] = 0x80; + for (i = 1; i < padding_len; i++) { + output[data_len + i] = 0x00; + } } -static cx_err_t get_zeros_padding(uint8_t *input, size_t in_len, size_t *data_len) { - if ((NULL == input) || (NULL == data_len)) { - return CX_INVALID_PARAMETER; - } - *data_len = in_len; - return CX_OK; +static cx_err_t get_zeros_padding(uint8_t *input, size_t in_len, size_t *data_len) +{ + if ((NULL == input) || (NULL == data_len)) { + return CX_INVALID_PARAMETER; + } + *data_len = in_len; + return CX_OK; } -static inline uint32_t neq_zero(uint32_t x) { - return (x|-x) >> 31; +static inline uint32_t neq_zero(uint32_t x) +{ + return (x | -x) >> 31; } -static inline uint32_t conditional_choice(uint32_t a, uint32_t b, uint32_t cond) { - // Return a if cond is non zero, otherwise return b - return (a ^ b) ^ (b & (-cond)); +static inline uint32_t conditional_choice(uint32_t a, uint32_t b, uint32_t cond) +{ + // Return a if cond is non zero, otherwise return b + return (a ^ b) ^ (b & (-cond)); } -static cx_err_t get_one_and_zeros_padding(uint8_t *input, size_t in_len, size_t *data_len) { - if ((NULL == input) || (NULL == data_len)) { - return CX_INVALID_PARAMETER; - } - int i; - // keeps track of consecutive zeroes - uint32_t acc = 0; - // result[0] is 1 if the padding is correct - // result[1] serves as a dummy value for constant time purposes - uint8_t result[2] = {0}; - // padsize[0] will contain the padding length - // padsize[1] is a dummy value - uint8_t padsize[2] = {0}; - - for (i = in_len - 1; i >= 0; i--) { - uint32_t is_0x80 = neq_zero(input[i] ^ 0x80); // 0 if current byte == 0x80 - uint32_t is_zero = neq_zero(acc); - result[is_0x80 | is_zero] = 1; // result[0] == 1 if t==0 and is_zero==0 - padsize[is_0x80 | is_zero] = i; // update padded_size the same wa - acc |= input[i]; - } - *data_len = padsize[0]; // this is 0 if padding is invalid - uint32_t is_correct = neq_zero((uint32_t)result[0]); - return conditional_choice(CX_OK, CX_INVALID_PARAMETER, is_correct); +static cx_err_t get_one_and_zeros_padding(uint8_t *input, size_t in_len, size_t *data_len) +{ + if ((NULL == input) || (NULL == data_len)) { + return CX_INVALID_PARAMETER; + } + int i; + // keeps track of consecutive zeroes + uint32_t acc = 0; + // result[0] is 1 if the padding is correct + // result[1] serves as a dummy value for constant time purposes + uint8_t result[2] = {0}; + // padsize[0] will contain the padding length + // padsize[1] is a dummy value + uint8_t padsize[2] = {0}; + + for (i = in_len - 1; i >= 0; i--) { + uint32_t is_0x80 = neq_zero(input[i] ^ 0x80); // 0 if current byte == 0x80 + uint32_t is_zero = neq_zero(acc); + result[is_0x80 | is_zero] = 1; // result[0] == 1 if t==0 and is_zero==0 + padsize[is_0x80 | is_zero] = i; // update padded_size the same wa + acc |= input[i]; + } + *data_len = padsize[0]; // this is 0 if padding is invalid + uint32_t is_correct = neq_zero((uint32_t) result[0]); + return conditional_choice(CX_OK, CX_INVALID_PARAMETER, is_correct); } -static cx_err_t ecb_func(cx_cipher_context_t *ctx, uint32_t operation, size_t len, const uint8_t *input, uint8_t *output) { - uint32_t block_size = ctx->cipher_info->block_size; - cx_err_t error = CX_INTERNAL_ERROR; +static cx_err_t ecb_func(cx_cipher_context_t *ctx, + uint32_t operation, + size_t len, + const uint8_t *input, + uint8_t *output) +{ + uint32_t block_size = ctx->cipher_info->block_size; + cx_err_t error = CX_INTERNAL_ERROR; - if (len % block_size) { - return CX_INVALID_PARAMETER_VALUE; - } - while (len > 0) { - if (CX_ENCRYPT == operation) { - CX_CHECK(ctx->cipher_info->base->enc_func(input, output)); - } else if (CX_DECRYPT == operation) { - CX_CHECK(ctx->cipher_info->base->dec_func(input, output)); + if (len % block_size) { + return CX_INVALID_PARAMETER_VALUE; } - else { - return CX_INVALID_PARAMETER_VALUE; + while (len > 0) { + if (CX_ENCRYPT == operation) { + CX_CHECK(ctx->cipher_info->base->enc_func(input, output)); + } + else if (CX_DECRYPT == operation) { + CX_CHECK(ctx->cipher_info->base->dec_func(input, output)); + } + else { + return CX_INVALID_PARAMETER_VALUE; + } + input += block_size; + output += block_size; + len -= block_size; } - input += block_size; - output += block_size; - len -= block_size; - } - error = CX_OK; + error = CX_OK; - end: +end: return error; } -static cx_err_t cbc_func(cx_cipher_context_t *ctx, uint32_t operation, size_t len, - const uint8_t *input, uint8_t *output) { - - uint8_t block[CX_MAX_BLOCK_SIZE]; - uint32_t block_size = ctx->cipher_info->block_size; - cx_err_t error = CX_INTERNAL_ERROR; - - if (len % block_size) { - return CX_INVALID_PARAMETER_VALUE; - } - while (len > 0) { - if (CX_DECRYPT == operation) { - CX_CHECK(ctx->cipher_info->base->dec_func(input, output)); - output += block_size; +static cx_err_t cbc_func(cx_cipher_context_t *ctx, + uint32_t operation, + size_t len, + const uint8_t *input, + uint8_t *output) +{ + uint8_t block[CX_MAX_BLOCK_SIZE]; + uint32_t block_size = ctx->cipher_info->block_size; + cx_err_t error = CX_INTERNAL_ERROR; + + if (len % block_size) { + return CX_INVALID_PARAMETER_VALUE; } - else { - CX_CHECK(ctx->cipher_info->base->enc_func(input, block)); - if (CX_ENCRYPT == operation) { - memcpy(output, block, block_size); - output += block_size; - } + while (len > 0) { + if (CX_DECRYPT == operation) { + CX_CHECK(ctx->cipher_info->base->dec_func(input, output)); + output += block_size; + } + else { + CX_CHECK(ctx->cipher_info->base->enc_func(input, block)); + if (CX_ENCRYPT == operation) { + memcpy(output, block, block_size); + output += block_size; + } + } + input += block_size; + len -= block_size; } - input += block_size; - len -= block_size; - } - memcpy(ctx->sig, block, block_size); - error = CX_OK; + memcpy(ctx->sig, block, block_size); + error = CX_OK; - end: +end: return error; } -static size_t cx_cipher_verify_block(uint8_t *block, uint8_t *block_ref, size_t block_size) { - return (memcmp(block, block_ref, block_size) == 0) ? block_size : 0; +static size_t cx_cipher_verify_block(uint8_t *block, uint8_t *block_ref, size_t block_size) +{ + return (memcmp(block, block_ref, block_size) == 0) ? block_size : 0; } -cx_err_t cx_cipher_init(cx_cipher_context_t *ctx) { - if (NULL == ctx) { - return CX_INVALID_PARAMETER; - } - memset(ctx, 0, sizeof(cx_cipher_context_t)); - return CX_OK; +cx_err_t cx_cipher_init(cx_cipher_context_t *ctx) +{ + if (NULL == ctx) { + return CX_INVALID_PARAMETER; + } + memset(ctx, 0, sizeof(cx_cipher_context_t)); + return CX_OK; } -cx_err_t cx_cipher_setup(cx_cipher_context_t *ctx, const cx_cipher_id_t type, uint32_t mode) { - if (NULL == ctx) { - return CX_INVALID_PARAMETER; - } - const cx_cipher_info_t *info = cx_cipher_get_info(type); - if (NULL == info) { - return CX_INVALID_PARAMETER; - } - if (NULL == ctx->cipher_key) { - return CX_INVALID_PARAMETER; - } - switch (mode) { - case CX_CHAIN_CTR: - switch (type) { - case CX_CIPHER_AES_128: - case CX_CIPHER_AES_192: - case CX_CIPHER_AES_256: - ctx->mode = mode; - break; - default: - return CX_INVALID_PARAMETER_VALUE; - } - break; - case CX_CHAIN_ECB: - case CX_CHAIN_CBC: - ctx->mode = mode; - break; - default: - return CX_INVALID_PARAMETER_VALUE; - } - ctx->cipher_info = info; - return CX_OK; - +cx_err_t cx_cipher_setup(cx_cipher_context_t *ctx, const cx_cipher_id_t type, uint32_t mode) +{ + if (NULL == ctx) { + return CX_INVALID_PARAMETER; + } + const cx_cipher_info_t *info = cx_cipher_get_info(type); + if (NULL == info) { + return CX_INVALID_PARAMETER; + } + if (NULL == ctx->cipher_key) { + return CX_INVALID_PARAMETER; + } + switch (mode) { + case CX_CHAIN_CTR: + switch (type) { + case CX_CIPHER_AES_128: + case CX_CIPHER_AES_192: + case CX_CIPHER_AES_256: + ctx->mode = mode; + break; + default: + return CX_INVALID_PARAMETER_VALUE; + } + break; + case CX_CHAIN_ECB: + case CX_CHAIN_CBC: + ctx->mode = mode; + break; + default: + return CX_INVALID_PARAMETER_VALUE; + } + ctx->cipher_info = info; + return CX_OK; } -cx_err_t cx_cipher_setkey(cx_cipher_context_t *ctx, const uint8_t *key, uint32_t key_bitlen, uint32_t operation) { - uint32_t op_mode; +cx_err_t cx_cipher_setkey(cx_cipher_context_t *ctx, + const uint8_t *key, + uint32_t key_bitlen, + uint32_t operation) +{ + uint32_t op_mode; if ((NULL == ctx) || (NULL == key) || (NULL == ctx->cipher_info)) { - return CX_INVALID_PARAMETER; + return CX_INVALID_PARAMETER; } if (ctx->cipher_info->key_bitlen != key_bitlen) { - return CX_INVALID_PARAMETER_SIZE; + return CX_INVALID_PARAMETER_SIZE; } - if ( (operation != CX_ENCRYPT) && (operation != CX_DECRYPT) - && (operation != CX_SIGN) && (operation != CX_VERIFY)) { - return CX_INVALID_PARAMETER_VALUE; + if ((operation != CX_ENCRYPT) && (operation != CX_DECRYPT) && (operation != CX_SIGN) + && (operation != CX_VERIFY)) { + return CX_INVALID_PARAMETER_VALUE; } ctx->key_bitlen = key_bitlen; ctx->operation = operation; @@ -249,223 +273,252 @@ cx_err_t cx_cipher_setkey(cx_cipher_context_t *ctx, const uint8_t *key, uint32_t return ctx->cipher_info->base->setkey_func(ctx->cipher_key, op_mode, key, key_bitlen); } -cx_err_t cx_cipher_setiv(cx_cipher_context_t *ctx, const uint8_t *iv, size_t iv_len) { +cx_err_t cx_cipher_setiv(cx_cipher_context_t *ctx, const uint8_t *iv, size_t iv_len) +{ if ((NULL == ctx) || (NULL == ctx->cipher_info)) { - return CX_INVALID_PARAMETER; + return CX_INVALID_PARAMETER; } if (CX_CHAIN_ECB == ctx->mode) { - return CX_OK; + return CX_OK; } if ((NULL == iv) && (0 != iv_len)) { - return CX_INVALID_PARAMETER_VALUE; + return CX_INVALID_PARAMETER_VALUE; } if ((0 != iv_len) && (ctx->cipher_info->iv_size != iv_len)) { - return CX_INVALID_PARAMETER_VALUE; + return CX_INVALID_PARAMETER_VALUE; } memcpy(ctx->iv, iv, iv_len); ctx->iv_size = iv_len; if (CX_CHAIN_CBC == ctx->mode) { - ctx->cipher_info->base->enc_func(ctx->iv, ctx->iv); + ctx->cipher_info->base->enc_func(ctx->iv, ctx->iv); } return CX_OK; } -cx_err_t cx_cipher_set_padding(cx_cipher_context_t *ctx, uint32_t padding) { - if ((NULL == ctx) || (NULL == ctx->cipher_info)) { - return CX_INVALID_PARAMETER; - } - switch (padding) { - case CX_PAD_NONE: - ctx->add_padding = NULL; - ctx->get_padding = get_no_padding; - return CX_OK; - case CX_PAD_ISO9797M1: - ctx->add_padding = add_zeros_padding; - ctx->get_padding = get_zeros_padding; - return CX_OK; - case CX_PAD_ISO9797M2: - ctx->add_padding = add_one_and_zeros_padding; - ctx->get_padding = get_one_and_zeros_padding; - return CX_OK; - default: - return CX_INVALID_PARAMETER_VALUE; - } +cx_err_t cx_cipher_set_padding(cx_cipher_context_t *ctx, uint32_t padding) +{ + if ((NULL == ctx) || (NULL == ctx->cipher_info)) { + return CX_INVALID_PARAMETER; + } + switch (padding) { + case CX_PAD_NONE: + ctx->add_padding = NULL; + ctx->get_padding = get_no_padding; + return CX_OK; + case CX_PAD_ISO9797M1: + ctx->add_padding = add_zeros_padding; + ctx->get_padding = get_zeros_padding; + return CX_OK; + case CX_PAD_ISO9797M2: + ctx->add_padding = add_one_and_zeros_padding; + ctx->get_padding = get_one_and_zeros_padding; + return CX_OK; + default: + return CX_INVALID_PARAMETER_VALUE; + } } -cx_err_t cx_cipher_update(cx_cipher_context_t *ctx, const uint8_t *input, size_t in_len, uint8_t *output, size_t *out_len) { +cx_err_t cx_cipher_update(cx_cipher_context_t *ctx, + const uint8_t *input, + size_t in_len, + uint8_t *output, + size_t *out_len) +{ size_t remain_len; size_t block_size; cx_err_t error = CX_INTERNAL_ERROR; if ((NULL == ctx) || (NULL == ctx->cipher_info) || (NULL == out_len)) { - return CX_INVALID_PARAMETER; + return CX_INVALID_PARAMETER; } if (NULL == input) { - return CX_INVALID_PARAMETER_VALUE; + return CX_INVALID_PARAMETER_VALUE; } CX_CHECK(cx_cipher_check_out_len(ctx, in_len, *out_len)); - *out_len = 0; + *out_len = 0; block_size = ctx->cipher_info->block_size; switch (ctx->mode) { - case CX_CHAIN_ECB: - case CX_CHAIN_CBC: - if (in_len + ctx->unprocessed_len < block_size) { - memcpy(&(ctx->unprocessed_data[ctx->unprocessed_len]), input, in_len); - ctx->unprocessed_len += in_len; + case CX_CHAIN_ECB: + case CX_CHAIN_CBC: + if (in_len + ctx->unprocessed_len < block_size) { + memcpy(&(ctx->unprocessed_data[ctx->unprocessed_len]), input, in_len); + ctx->unprocessed_len += in_len; + return CX_OK; + } + if (ctx->unprocessed_len != 0) { + remain_len = block_size - ctx->unprocessed_len; + memcpy(&(ctx->unprocessed_data[ctx->unprocessed_len]), input, remain_len); + if (CX_CHAIN_ECB == ctx->mode) { + CX_CHECK( + ecb_func(ctx, ctx->operation, block_size, ctx->unprocessed_data, output)); + } + else { + CX_CHECK( + cbc_func(ctx, ctx->operation, block_size, ctx->unprocessed_data, output)); + } + if (ctx->operation != CX_SIGN) { + output += block_size; + } + *out_len += block_size; + ctx->unprocessed_len = 0; + input += remain_len; + in_len -= remain_len; + } + if (in_len != 0) { + remain_len = in_len % block_size; + if ((remain_len == 0) && (ctx->operation == CX_DECRYPT) + && (ctx->add_padding != NULL)) { + remain_len = block_size; + } + memcpy(ctx->unprocessed_data, &(input[in_len - remain_len]), remain_len); + ctx->unprocessed_len += remain_len; + in_len -= remain_len; + } + if (in_len) { + if (CX_CHAIN_ECB == ctx->mode) { + CX_CHECK(ecb_func(ctx, ctx->operation, in_len, input, output)); + } + else { + CX_CHECK(cbc_func(ctx, ctx->operation, in_len, input, output)); + } + } + *out_len = in_len; return CX_OK; - } - if (ctx->unprocessed_len != 0) { - remain_len = block_size - ctx->unprocessed_len; - memcpy(&( ctx->unprocessed_data[ctx->unprocessed_len]), input, remain_len); - if (CX_CHAIN_ECB == ctx->mode) { - CX_CHECK(ecb_func(ctx, ctx->operation, block_size, ctx->unprocessed_data, output)); - } else { - CX_CHECK(cbc_func(ctx, ctx->operation, block_size, ctx->unprocessed_data, output)); - } - if (ctx->operation != CX_SIGN) { - output += block_size; - } - *out_len += block_size; - ctx->unprocessed_len = 0; - input += remain_len; - in_len -= remain_len; - } - if (in_len != 0) { - remain_len = in_len % block_size; - if ((remain_len == 0) && (ctx->operation == CX_DECRYPT) && (ctx->add_padding != NULL)) { - remain_len = block_size; - } - memcpy(ctx->unprocessed_data, &(input[in_len - remain_len]), remain_len); - ctx->unprocessed_len += remain_len; - in_len -= remain_len; - } - if (in_len) { - if (CX_CHAIN_ECB == ctx->mode) { - CX_CHECK(ecb_func(ctx, ctx->operation, in_len, input, output)); - } - else { - CX_CHECK(cbc_func(ctx, ctx->operation, in_len, input, output)); - } - } - *out_len = in_len; - return CX_OK; - case CX_CHAIN_CTR: - CX_CHECK(ctx->cipher_info->base->ctr_func(ctx->cipher_key, in_len, &ctx->unprocessed_len, - ctx->iv, ctx->unprocessed_data, input, output)); - *out_len = in_len; - return CX_OK; - default: - return CX_INVALID_PARAMETER_VALUE; + case CX_CHAIN_CTR: + CX_CHECK(ctx->cipher_info->base->ctr_func(ctx->cipher_key, + in_len, + &ctx->unprocessed_len, + ctx->iv, + ctx->unprocessed_data, + input, + output)); + *out_len = in_len; + return CX_OK; + default: + return CX_INVALID_PARAMETER_VALUE; } - end: - return error; - +end: + return error; } -cx_err_t cx_cipher_finish(cx_cipher_context_t *ctx, uint8_t *output, size_t *out_len) { - cx_err_t error = CX_INTERNAL_ERROR; - if ((NULL == ctx) || (NULL == ctx->cipher_info) || (NULL == out_len)) { - return CX_INVALID_PARAMETER; - } - - *out_len = 0; - switch (ctx->mode) { - case CX_CHAIN_CTR: - error = CX_OK; - break; - case CX_CHAIN_ECB: - case CX_CHAIN_CBC: - if ((CX_ENCRYPT == ctx->operation) || (CX_SIGN == ctx->operation) || (CX_VERIFY == ctx->operation)) { - if (NULL == ctx->add_padding) { - if (ctx->unprocessed_len != 0) { - goto end; - } - error = CX_OK; - goto end; - } - if ((add_zeros_padding == ctx->add_padding) && (ctx->unprocessed_len == 0)) { - *out_len = 0; - error = CX_OK; - goto end; - } - ctx->add_padding(ctx->unprocessed_data, ctx->cipher_info->block_size, - ctx->unprocessed_len); - } - if (get_no_padding != ctx->get_padding) { - ctx->unprocessed_len = ctx->cipher_info->block_size; - } - if (CX_CHAIN_ECB == ctx->mode) { - CX_CHECK(ecb_func(ctx, ctx->operation, ctx->unprocessed_len, ctx->unprocessed_data, output)); - } - else { - CX_CHECK(cbc_func(ctx, ctx->operation, ctx->unprocessed_len, - ctx->unprocessed_data, output)); - } - - if ((CX_DECRYPT == ctx->operation) && (NULL != ctx->get_padding)) { - error = ctx->get_padding(output, ctx->unprocessed_len, out_len); - goto end; - } - - *out_len = ctx->unprocessed_len; - error = CX_OK; - break; - default: - error = CX_INVALID_PARAMETER_VALUE; - break; - } - end: +cx_err_t cx_cipher_finish(cx_cipher_context_t *ctx, uint8_t *output, size_t *out_len) +{ + cx_err_t error = CX_INTERNAL_ERROR; + if ((NULL == ctx) || (NULL == ctx->cipher_info) || (NULL == out_len)) { + return CX_INVALID_PARAMETER; + } + + *out_len = 0; + switch (ctx->mode) { + case CX_CHAIN_CTR: + error = CX_OK; + break; + case CX_CHAIN_ECB: + case CX_CHAIN_CBC: + if ((CX_ENCRYPT == ctx->operation) || (CX_SIGN == ctx->operation) + || (CX_VERIFY == ctx->operation)) { + if (NULL == ctx->add_padding) { + if (ctx->unprocessed_len != 0) { + goto end; + } + error = CX_OK; + goto end; + } + if ((add_zeros_padding == ctx->add_padding) && (ctx->unprocessed_len == 0)) { + *out_len = 0; + error = CX_OK; + goto end; + } + ctx->add_padding( + ctx->unprocessed_data, ctx->cipher_info->block_size, ctx->unprocessed_len); + } + if (get_no_padding != ctx->get_padding) { + ctx->unprocessed_len = ctx->cipher_info->block_size; + } + if (CX_CHAIN_ECB == ctx->mode) { + CX_CHECK(ecb_func( + ctx, ctx->operation, ctx->unprocessed_len, ctx->unprocessed_data, output)); + } + else { + CX_CHECK(cbc_func( + ctx, ctx->operation, ctx->unprocessed_len, ctx->unprocessed_data, output)); + } + + if ((CX_DECRYPT == ctx->operation) && (NULL != ctx->get_padding)) { + error = ctx->get_padding(output, ctx->unprocessed_len, out_len); + goto end; + } + + *out_len = ctx->unprocessed_len; + error = CX_OK; + break; + default: + error = CX_INVALID_PARAMETER_VALUE; + break; + } +end: ctx->cipher_info->base->ctx_reset(); return error; } -cx_err_t cx_cipher_mac(cx_cipher_context_t *ctx, uint8_t *output, size_t *out_len, size_t *finish_len) { - // Only in CBC - if (CX_VERIFY == ctx->operation) { - *finish_len = cx_cipher_verify_block(ctx->sig, output, ctx->cipher_info->block_size); - *out_len = 0; - } - else if (CX_SIGN == ctx->operation) { - memcpy(output, ctx->sig, ctx->cipher_info->block_size); - *finish_len = ctx->cipher_info->block_size; - *out_len = 0; - } - else { +cx_err_t cx_cipher_mac(cx_cipher_context_t *ctx, + uint8_t *output, + size_t *out_len, + size_t *finish_len) +{ + // Only in CBC + if (CX_VERIFY == ctx->operation) { + *finish_len = cx_cipher_verify_block(ctx->sig, output, ctx->cipher_info->block_size); + *out_len = 0; + } + else if (CX_SIGN == ctx->operation) { + memcpy(output, ctx->sig, ctx->cipher_info->block_size); + *finish_len = ctx->cipher_info->block_size; + *out_len = 0; + } + else { + return CX_OK; + } return CX_OK; - } - return CX_OK; } -cx_err_t cx_cipher_enc_dec(cx_cipher_context_t *ctx, const uint8_t *iv, size_t iv_len, const uint8_t *input, size_t in_len, - uint8_t *output, size_t *out_len) { - cx_err_t error = CX_INTERNAL_ERROR; - size_t finish_len = 0; - - CX_CHECK(cx_cipher_setiv(ctx, iv, iv_len)); - CX_CHECK(cx_cipher_update(ctx, input, in_len, output, out_len)); - if (ctx->add_padding != NULL) { - finish_len = *out_len; - } - CX_CHECK(cx_cipher_finish(ctx, output + finish_len, &finish_len)); - CX_CHECK(cx_cipher_mac(ctx, output, out_len, &finish_len)); - *out_len += finish_len; - - end: +cx_err_t cx_cipher_enc_dec(cx_cipher_context_t *ctx, + const uint8_t *iv, + size_t iv_len, + const uint8_t *input, + size_t in_len, + uint8_t *output, + size_t *out_len) +{ + cx_err_t error = CX_INTERNAL_ERROR; + size_t finish_len = 0; + + CX_CHECK(cx_cipher_setiv(ctx, iv, iv_len)); + CX_CHECK(cx_cipher_update(ctx, input, in_len, output, out_len)); + if (ctx->add_padding != NULL) { + finish_len = *out_len; + } + CX_CHECK(cx_cipher_finish(ctx, output + finish_len, &finish_len)); + CX_CHECK(cx_cipher_mac(ctx, output, out_len, &finish_len)); + *out_len += finish_len; + +end: return error; } -void cx_cipher_reset(cx_cipher_context_t *ctx) { - memset(ctx->iv, 0, MAX_IV_LENGTH); - memset(ctx->unprocessed_data, 0, MAX_BLOCK_LENGTH); - ctx->unprocessed_len = 0; - ctx->iv_size = 0; +void cx_cipher_reset(cx_cipher_context_t *ctx) +{ + memset(ctx->iv, 0, MAX_IV_LENGTH); + memset(ctx->unprocessed_data, 0, MAX_BLOCK_LENGTH); + ctx->unprocessed_len = 0; + ctx->iv_size = 0; } #ifdef UNITTEST @@ -474,62 +527,65 @@ void cx_cipher_reset(cx_cipher_context_t *ctx) { #include #include #include -static void test_iso9797_method2_unpad(void **state) { - uint8_t buf1[8] = {0, 1, 2, 3, 4, 5, 6, 0x80}; - size_t unpadded_size = 0; +static void test_iso9797_method2_unpad(void **state) +{ + uint8_t buf1[8] = {0, 1, 2, 3, 4, 5, 6, 0x80}; + size_t unpadded_size = 0; - assert_int_equal(get_one_and_zeros_padding(buf1, 8, &unpadded_size), CX_OK); - assert_int_equal(unpadded_size, 7); + assert_int_equal(get_one_and_zeros_padding(buf1, 8, &unpadded_size), CX_OK); + assert_int_equal(unpadded_size, 7); - uint8_t buf2[8] = {0, 1, 2, 3, 0x80, 0, 0, 0}; - unpadded_size = 0; + uint8_t buf2[8] = {0, 1, 2, 3, 0x80, 0, 0, 0}; + unpadded_size = 0; - assert_int_equal(get_one_and_zeros_padding(buf2, 8, &unpadded_size), CX_OK); - assert_int_equal(unpadded_size, 4); + assert_int_equal(get_one_and_zeros_padding(buf2, 8, &unpadded_size), CX_OK); + assert_int_equal(unpadded_size, 4); - unpadded_size = 0; - uint8_t buf3[8] = {0, 1, 2, 3, 4, 5, 6, 7}; + unpadded_size = 0; + uint8_t buf3[8] = {0, 1, 2, 3, 4, 5, 6, 7}; - assert_int_equal(get_one_and_zeros_padding(buf3, 8, &unpadded_size), CX_INVALID_PARAMETER); + assert_int_equal(get_one_and_zeros_padding(buf3, 8, &unpadded_size), CX_INVALID_PARAMETER); - uint8_t buf4[8] = {0, 1, 2, 3, 4, 5, 0x80, 7}; - unpadded_size = 0; + uint8_t buf4[8] = {0, 1, 2, 3, 4, 5, 0x80, 7}; + unpadded_size = 0; - assert_int_equal(get_one_and_zeros_padding(buf4, 8, &unpadded_size), CX_INVALID_PARAMETER); + assert_int_equal(get_one_and_zeros_padding(buf4, 8, &unpadded_size), CX_INVALID_PARAMETER); - uint8_t buf5[8] = {0x80, 0, 0, 0, 0, 0, 0, 0}; - unpadded_size = 0; + uint8_t buf5[8] = {0x80, 0, 0, 0, 0, 0, 0, 0}; + unpadded_size = 0; - assert_int_equal(get_one_and_zeros_padding(buf5, 8, &unpadded_size), CX_OK); - assert_int_equal(unpadded_size, 0); + assert_int_equal(get_one_and_zeros_padding(buf5, 8, &unpadded_size), CX_OK); + assert_int_equal(unpadded_size, 0); } -static void test_iso9797_method2_pad(void **state) { - uint8_t buf1[8] = {0}; - const uint8_t buf1_padded[8] = {0x80, 0, 0, 0, 0, 0, 0, 0}; +static void test_iso9797_method2_pad(void **state) +{ + uint8_t buf1[8] = {0}; + const uint8_t buf1_padded[8] = {0x80, 0, 0, 0, 0, 0, 0, 0}; - add_one_and_zeros_padding(buf1, 8, 0); - assert_memory_equal(buf1, buf1_padded, sizeof(buf1_padded)); + add_one_and_zeros_padding(buf1, 8, 0); + assert_memory_equal(buf1, buf1_padded, sizeof(buf1_padded)); - uint8_t buf2[8] = {0xaa, 0xbb, 0xcc}; - const uint8_t buf2_padded[8] = {0xaa, 0xbb, 0xcc, 0x80, 0, 0, 0, 0}; + uint8_t buf2[8] = {0xaa, 0xbb, 0xcc}; + const uint8_t buf2_padded[8] = {0xaa, 0xbb, 0xcc, 0x80, 0, 0, 0, 0}; - add_one_and_zeros_padding(buf2, 8, 3); - assert_memory_equal(buf2, buf2_padded, sizeof(buf2_padded)); + add_one_and_zeros_padding(buf2, 8, 3); + assert_memory_equal(buf2, buf2_padded, sizeof(buf2_padded)); - uint8_t buf3[16] = {0, 1, 2, 3, 4, 5, 6, 7}; - const uint8_t buf3_padded[16] = {0, 1, 2, 3, 4, 5, 6, 7, 0x80, 0, 0, 0, 0, 0, 0, 0}; + uint8_t buf3[16] = {0, 1, 2, 3, 4, 5, 6, 7}; + const uint8_t buf3_padded[16] = {0, 1, 2, 3, 4, 5, 6, 7, 0x80, 0, 0, 0, 0, 0, 0, 0}; - add_one_and_zeros_padding(buf3, 16, 8); - assert_memory_equal(buf3, buf3_padded, sizeof(buf3_padded)); + add_one_and_zeros_padding(buf3, 16, 8); + assert_memory_equal(buf3, buf3_padded, sizeof(buf3_padded)); } -int main() { - const struct CMUnitTest tests[] = { - cmocka_unit_test(test_iso9797_method2_pad), - cmocka_unit_test(test_iso9797_method2_unpad), - }; +int main() +{ + const struct CMUnitTest tests[] = { + cmocka_unit_test(test_iso9797_method2_pad), + cmocka_unit_test(test_iso9797_method2_unpad), + }; - return cmocka_run_group_tests(tests, NULL, NULL); + return cmocka_run_group_tests(tests, NULL, NULL); } -#endif // UNITTEST +#endif // UNITTEST diff --git a/lib_cxng/src/cx_cipher.h b/lib_cxng/src/cx_cipher.h index 47ddba813..cc8fa02ce 100644 --- a/lib_cxng/src/cx_cipher.h +++ b/lib_cxng/src/cx_cipher.h @@ -1,20 +1,20 @@ /******************************************************************************* -* Ledger Nano S - Secure firmware -* (c) 2022 Ledger -* -* Licensed under the Apache License, Version 2.0 (the "License"); -* you may not use this file except in compliance with the License. -* You may obtain a copy of the License at -* -* http://www.apache.org/licenses/LICENSE-2.0 -* -* Unless required by applicable law or agreed to in writing, software -* distributed under the License is distributed on an "AS IS" BASIS, -* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -* See the License for the specific language governing permissions and -* limitations under the License. -********************************************************************************/ + * Ledger Nano S - Secure firmware + * (c) 2022 Ledger + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT 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 CX_CIPHER_H #define CX_CIPHER_H @@ -31,7 +31,7 @@ extern const cx_cipher_info_t cx_aes_256_info; /** HW support */ cx_err_t cx_aes_set_key_hw(const cx_aes_key_t *keys, uint32_t mode); cx_err_t cx_aes_block_hw(const uint8_t *inblock, uint8_t *outblock); -void cx_aes_reset_hw(void); -#endif // HAVE_AES +void cx_aes_reset_hw(void); +#endif // HAVE_AES #endif /* CX_CIPHER_H */ diff --git a/lib_cxng/src/cx_cmac.c b/lib_cxng/src/cx_cmac.c index 283b572c6..9c5da8635 100644 --- a/lib_cxng/src/cx_cmac.c +++ b/lib_cxng/src/cx_cmac.c @@ -6,165 +6,157 @@ #include "cx_cmac.h" #include -#define CMAC_CONSTANT_R_64 (0x1B) -#define CMAC_CONSTANT_R_128 (0x87) +#define CMAC_CONSTANT_R_64 (0x1B) +#define CMAC_CONSTANT_R_128 (0x87) -cx_err_t cx_cmac_start(cx_cipher_context_t *ctx, - const uint8_t *key, - size_t key_bitlen) { - cx_err_t error; +cx_err_t cx_cmac_start(cx_cipher_context_t *ctx, const uint8_t *key, size_t key_bitlen) +{ + cx_err_t error; - if ((NULL == ctx) || (NULL == key)) { - return CX_INVALID_PARAMETER; - } + if ((NULL == ctx) || (NULL == key)) { + return CX_INVALID_PARAMETER; + } - CX_CHECK(cx_cipher_setkey(ctx, key, key_bitlen, CX_ENCRYPT)); + CX_CHECK(cx_cipher_setkey(ctx, key, key_bitlen, CX_ENCRYPT)); - ctx->cmac_ctx = &G_cx.cmac; - memset(ctx->cmac_ctx->state, 0, sizeof(ctx->cmac_ctx->state)); + ctx->cmac_ctx = &G_cx.cmac; + memset(ctx->cmac_ctx->state, 0, sizeof(ctx->cmac_ctx->state)); - end: +end: return error; - } -cx_err_t cx_cmac_update(cx_cipher_context_t *ctx, - const uint8_t *input, - size_t in_len) { - cx_err_t error; - size_t out_len = ctx->cipher_info->block_size; - size_t i, n; - size_t *current_len; - - if ( (NULL == ctx) - || (NULL == ctx->cipher_info) - || (NULL == input) - || (NULL == ctx->cmac_ctx)) { - return CX_INVALID_PARAMETER; - } - - current_len = &ctx->cmac_ctx->unprocessed_len; - - if ( (*current_len > 0) - && (in_len > ctx->cipher_info->block_size - *current_len)) { - memcpy(ctx->cmac_ctx->unprocessed_block + *current_len, - input, - ctx->cipher_info->block_size - *current_len); - cx_memxor(ctx->cmac_ctx->state, - ctx->cmac_ctx->unprocessed_block, - ctx->cipher_info->block_size); - CX_CHECK(cx_cipher_update(ctx, ctx->cmac_ctx->state, ctx->cipher_info->block_size, - ctx->cmac_ctx->state, &out_len)); - input += ctx->cipher_info->block_size - *current_len; - in_len -= ctx->cipher_info->block_size - *current_len; - *current_len = 0; - } - - n = (in_len + ctx->cipher_info->block_size - 1) / ctx->cipher_info->block_size; - - for (i = 1; i < n; i++) { - cx_memxor(ctx->cmac_ctx->state, input, ctx->cipher_info->block_size); - CX_CHECK(cx_cipher_update(ctx, ctx->cmac_ctx->state, ctx->cipher_info->block_size, - ctx->cmac_ctx->state, &out_len)); - in_len -= ctx->cipher_info->block_size; - input += ctx->cipher_info->block_size; - } - - if (in_len > 0) { - memcpy(ctx->cmac_ctx->unprocessed_block + *current_len, - input, - in_len); - *current_len += in_len; - } - - error = CX_OK; - end: +cx_err_t cx_cmac_update(cx_cipher_context_t *ctx, const uint8_t *input, size_t in_len) +{ + cx_err_t error; + size_t out_len = ctx->cipher_info->block_size; + size_t i, n; + size_t *current_len; + + if ((NULL == ctx) || (NULL == ctx->cipher_info) || (NULL == input) || (NULL == ctx->cmac_ctx)) { + return CX_INVALID_PARAMETER; + } + + current_len = &ctx->cmac_ctx->unprocessed_len; + + if ((*current_len > 0) && (in_len > ctx->cipher_info->block_size - *current_len)) { + memcpy(ctx->cmac_ctx->unprocessed_block + *current_len, + input, + ctx->cipher_info->block_size - *current_len); + cx_memxor( + ctx->cmac_ctx->state, ctx->cmac_ctx->unprocessed_block, ctx->cipher_info->block_size); + CX_CHECK(cx_cipher_update(ctx, + ctx->cmac_ctx->state, + ctx->cipher_info->block_size, + ctx->cmac_ctx->state, + &out_len)); + input += ctx->cipher_info->block_size - *current_len; + in_len -= ctx->cipher_info->block_size - *current_len; + *current_len = 0; + } + + n = (in_len + ctx->cipher_info->block_size - 1) / ctx->cipher_info->block_size; + + for (i = 1; i < n; i++) { + cx_memxor(ctx->cmac_ctx->state, input, ctx->cipher_info->block_size); + CX_CHECK(cx_cipher_update(ctx, + ctx->cmac_ctx->state, + ctx->cipher_info->block_size, + ctx->cmac_ctx->state, + &out_len)); + in_len -= ctx->cipher_info->block_size; + input += ctx->cipher_info->block_size; + } + + if (in_len > 0) { + memcpy(ctx->cmac_ctx->unprocessed_block + *current_len, input, in_len); + *current_len += in_len; + } + + error = CX_OK; +end: return error; - } -cx_err_t cx_cmac_shift_and_xor(uint8_t *output, - uint8_t *input, - size_t block_size) { +cx_err_t cx_cmac_shift_and_xor(uint8_t *output, uint8_t *input, size_t block_size) +{ + uint8_t mask; + uint8_t constant = 0x00; + uint8_t msb = 0x00; + size_t i; - uint8_t mask; - uint8_t constant = 0x00; - uint8_t msb = 0x00; - size_t i; - - switch (block_size) { + switch (block_size) { #ifdef HAVE_AES - case CX_AES_BLOCK_SIZE: - constant = CMAC_CONSTANT_R_128; - break; -#endif // HAVE_AES - default: - return CX_INVALID_PARAMETER_VALUE; - } - - for (i = 0; i < block_size ; i++) { - output[block_size - 1 - i] = input[block_size - 1 - i] << 1 | msb; - msb = input[block_size - 1 - i] >> 7; - } - - mask = - (input[0] >> 7); - output[block_size - 1] ^= constant & mask; - - return CX_OK; + case CX_AES_BLOCK_SIZE: + constant = CMAC_CONSTANT_R_128; + break; +#endif // HAVE_AES + default: + return CX_INVALID_PARAMETER_VALUE; + } + + for (i = 0; i < block_size; i++) { + output[block_size - 1 - i] = input[block_size - 1 - i] << 1 | msb; + msb = input[block_size - 1 - i] >> 7; + } + + mask = -(input[0] >> 7); + output[block_size - 1] ^= constant & mask; + + return CX_OK; } static cx_err_t cx_cmac_generate_subkeys(cx_cipher_context_t *ctx, - uint8_t* sub_key1, - uint8_t* sub_key2) { - cx_err_t error; - uint8_t L[CMAC_MAX_BLOCK_LENGTH]; - size_t out_len = ctx->cipher_info->block_size; - - memset(L, 0, CMAC_MAX_BLOCK_LENGTH); - CX_CHECK(cx_cipher_update(ctx, L, ctx->cipher_info->block_size, L, &out_len)); - CX_CHECK(cx_cmac_shift_and_xor(sub_key1, L , ctx->cipher_info->block_size)); - CX_CHECK(cx_cmac_shift_and_xor(sub_key2, sub_key1 , ctx->cipher_info->block_size)); - - end: + uint8_t *sub_key1, + uint8_t *sub_key2) +{ + cx_err_t error; + uint8_t L[CMAC_MAX_BLOCK_LENGTH]; + size_t out_len = ctx->cipher_info->block_size; + + memset(L, 0, CMAC_MAX_BLOCK_LENGTH); + CX_CHECK(cx_cipher_update(ctx, L, ctx->cipher_info->block_size, L, &out_len)); + CX_CHECK(cx_cmac_shift_and_xor(sub_key1, L, ctx->cipher_info->block_size)); + CX_CHECK(cx_cmac_shift_and_xor(sub_key2, sub_key1, ctx->cipher_info->block_size)); + +end: memset(L, 0, CMAC_MAX_BLOCK_LENGTH); return error; } -cx_err_t cx_cmac_finish(cx_cipher_context_t *ctx, - uint8_t *output) { - uint8_t sub_key1[CMAC_MAX_BLOCK_LENGTH]; - uint8_t sub_key2[CMAC_MAX_BLOCK_LENGTH]; - uint8_t last_block[CMAC_MAX_BLOCK_LENGTH]; - cx_err_t error; - size_t out_len = ctx->cipher_info->block_size; - - if ( (NULL == ctx) - || (NULL == ctx->cipher_info) - || (NULL == ctx->cmac_ctx) - || (NULL == output)) { - return CX_INVALID_PARAMETER; - } - - CX_CHECK(cx_cmac_generate_subkeys(ctx, sub_key1, sub_key2)); - - if (ctx->cmac_ctx->unprocessed_len < ctx->cipher_info->block_size) { - memcpy(last_block, ctx->cmac_ctx->unprocessed_block, ctx->cmac_ctx->unprocessed_len); - add_one_and_zeros_padding(last_block, ctx->cipher_info->block_size, ctx->cmac_ctx->unprocessed_len); - cx_memxor(last_block, sub_key2, ctx->cipher_info->block_size); - } - else { - cx_memxor(ctx->cmac_ctx->unprocessed_block, sub_key1, ctx->cipher_info->block_size); - memcpy(last_block, ctx->cmac_ctx->unprocessed_block, ctx->cipher_info->block_size); - } - - - cx_memxor(ctx->cmac_ctx->state, last_block, ctx->cipher_info->block_size); - CX_CHECK(cx_cipher_update(ctx, ctx->cmac_ctx->state, ctx->cipher_info->block_size, - ctx->cmac_ctx->state, &out_len)); - - memcpy(output, ctx->cmac_ctx->state, ctx->cipher_info->block_size); - - end: +cx_err_t cx_cmac_finish(cx_cipher_context_t *ctx, uint8_t *output) +{ + uint8_t sub_key1[CMAC_MAX_BLOCK_LENGTH]; + uint8_t sub_key2[CMAC_MAX_BLOCK_LENGTH]; + uint8_t last_block[CMAC_MAX_BLOCK_LENGTH]; + cx_err_t error; + size_t out_len = ctx->cipher_info->block_size; + + if ((NULL == ctx) || (NULL == ctx->cipher_info) || (NULL == ctx->cmac_ctx) + || (NULL == output)) { + return CX_INVALID_PARAMETER; + } + + CX_CHECK(cx_cmac_generate_subkeys(ctx, sub_key1, sub_key2)); + + if (ctx->cmac_ctx->unprocessed_len < ctx->cipher_info->block_size) { + memcpy(last_block, ctx->cmac_ctx->unprocessed_block, ctx->cmac_ctx->unprocessed_len); + add_one_and_zeros_padding( + last_block, ctx->cipher_info->block_size, ctx->cmac_ctx->unprocessed_len); + cx_memxor(last_block, sub_key2, ctx->cipher_info->block_size); + } + else { + cx_memxor(ctx->cmac_ctx->unprocessed_block, sub_key1, ctx->cipher_info->block_size); + memcpy(last_block, ctx->cmac_ctx->unprocessed_block, ctx->cipher_info->block_size); + } + + cx_memxor(ctx->cmac_ctx->state, last_block, ctx->cipher_info->block_size); + CX_CHECK(cx_cipher_update( + ctx, ctx->cmac_ctx->state, ctx->cipher_info->block_size, ctx->cmac_ctx->state, &out_len)); + + memcpy(output, ctx->cmac_ctx->state, ctx->cipher_info->block_size); + +end: memset(sub_key1, 0, CMAC_MAX_BLOCK_LENGTH); memset(sub_key2, 0, CMAC_MAX_BLOCK_LENGTH); explicit_bzero(ctx->cmac_ctx, sizeof(cx_cmac_context_t)); @@ -172,31 +164,28 @@ cx_err_t cx_cmac_finish(cx_cipher_context_t *ctx, } cx_err_t cx_cmac(const cx_cipher_id_t type, - const uint8_t *key, - size_t key_bitlen, - const uint8_t *input, - size_t in_len, - uint8_t *output) { - - cx_cipher_context_t ctx; - cx_err_t error; - cipher_key_t key_ctx; - - if ( (NULL == key) - || (NULL == input) - || (NULL == output)) { - return CX_INVALID_PARAMETER; - } - CX_CHECK(cx_cipher_init(&ctx)); - ctx.cipher_key = &key_ctx; - CX_CHECK(cx_cipher_setup(&ctx, type, CX_CHAIN_ECB)); - CX_CHECK(cx_cmac_start(&ctx, key, key_bitlen)); - CX_CHECK(cx_cmac_update(&ctx, input, in_len)); - CX_CHECK(cx_cmac_finish(&ctx, output)); - - end: + const uint8_t *key, + size_t key_bitlen, + const uint8_t *input, + size_t in_len, + uint8_t *output) +{ + cx_cipher_context_t ctx; + cx_err_t error; + cipher_key_t key_ctx; + + if ((NULL == key) || (NULL == input) || (NULL == output)) { + return CX_INVALID_PARAMETER; + } + CX_CHECK(cx_cipher_init(&ctx)); + ctx.cipher_key = &key_ctx; + CX_CHECK(cx_cipher_setup(&ctx, type, CX_CHAIN_ECB)); + CX_CHECK(cx_cmac_start(&ctx, key, key_bitlen)); + CX_CHECK(cx_cmac_update(&ctx, input, in_len)); + CX_CHECK(cx_cmac_finish(&ctx, output)); + +end: return error; } - -#endif // HAVE_CMAC +#endif // HAVE_CMAC diff --git a/lib_cxng/src/cx_cmac.h b/lib_cxng/src/cx_cmac.h index 2d6781fe9..f516776fa 100644 --- a/lib_cxng/src/cx_cmac.h +++ b/lib_cxng/src/cx_cmac.h @@ -8,10 +8,7 @@ #include #include - -cx_err_t cx_cmac_shift_and_xor(uint8_t *output, - uint8_t *input, - size_t block_size); -#endif // HAVE_CMAC +cx_err_t cx_cmac_shift_and_xor(uint8_t *output, uint8_t *input, size_t block_size); +#endif // HAVE_CMAC #endif /* CX_CMAC_H */ diff --git a/lib_cxng/src/cx_crc.h b/lib_cxng/src/cx_crc.h index 2ea47c958..ac1da5691 100644 --- a/lib_cxng/src/cx_crc.h +++ b/lib_cxng/src/cx_crc.h @@ -1,20 +1,20 @@ /******************************************************************************* -* Ledger Nano S - Secure firmware -* (c) 2022 Ledger -* -* Licensed under the Apache License, Version 2.0 (the "License"); -* you may not use this file except in compliance with the License. -* You may obtain a copy of the License at -* -* http://www.apache.org/licenses/LICENSE-2.0 -* -* Unless required by applicable law or agreed to in writing, software -* distributed under the License is distributed on an "AS IS" BASIS, -* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -* See the License for the specific language governing permissions and -* limitations under the License. -********************************************************************************/ + * Ledger Nano S - Secure firmware + * (c) 2022 Ledger + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + ********************************************************************************/ #ifdef HAVE_CRC diff --git a/lib_cxng/src/cx_crc16.c b/lib_cxng/src/cx_crc16.c index f4bef33bc..39e38c956 100644 --- a/lib_cxng/src/cx_crc16.c +++ b/lib_cxng/src/cx_crc16.c @@ -1,65 +1,68 @@ /******************************************************************************* -* Ledger Nano S - Secure firmware -* (c) 2022 Ledger -* -* Licensed under the Apache License, Version 2.0 (the "License"); -* you may not use this file except in compliance with the License. -* You may obtain a copy of the License at -* -* http://www.apache.org/licenses/LICENSE-2.0 -* -* Unless required by applicable law or agreed to in writing, software -* distributed under the License is distributed on an "AS IS" BASIS, -* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -* See the License for the specific language governing permissions and -* limitations under the License. -********************************************************************************/ + * Ledger Nano S - Secure firmware + * (c) 2022 Ledger + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + ********************************************************************************/ #ifdef HAVE_CRC #include "lcx_crc.h" #include "cx_ram.h" - static uint16_t const cx_ccitt[] = { - 0x0000, 0x1021, 0x2042, 0x3063, 0x4084, 0x50a5, 0x60c6, 0x70e7, 0x8108, 0x9129, 0xa14a, 0xb16b, 0xc18c, 0xd1ad, - 0xe1ce, 0xf1ef, 0x1231, 0x0210, 0x3273, 0x2252, 0x52b5, 0x4294, 0x72f7, 0x62d6, 0x9339, 0x8318, 0xb37b, 0xa35a, - 0xd3bd, 0xc39c, 0xf3ff, 0xe3de, 0x2462, 0x3443, 0x0420, 0x1401, 0x64e6, 0x74c7, 0x44a4, 0x5485, 0xa56a, 0xb54b, - 0x8528, 0x9509, 0xe5ee, 0xf5cf, 0xc5ac, 0xd58d, 0x3653, 0x2672, 0x1611, 0x0630, 0x76d7, 0x66f6, 0x5695, 0x46b4, - 0xb75b, 0xa77a, 0x9719, 0x8738, 0xf7df, 0xe7fe, 0xd79d, 0xc7bc, 0x48c4, 0x58e5, 0x6886, 0x78a7, 0x0840, 0x1861, - 0x2802, 0x3823, 0xc9cc, 0xd9ed, 0xe98e, 0xf9af, 0x8948, 0x9969, 0xa90a, 0xb92b, 0x5af5, 0x4ad4, 0x7ab7, 0x6a96, - 0x1a71, 0x0a50, 0x3a33, 0x2a12, 0xdbfd, 0xcbdc, 0xfbbf, 0xeb9e, 0x9b79, 0x8b58, 0xbb3b, 0xab1a, 0x6ca6, 0x7c87, - 0x4ce4, 0x5cc5, 0x2c22, 0x3c03, 0x0c60, 0x1c41, 0xedae, 0xfd8f, 0xcdec, 0xddcd, 0xad2a, 0xbd0b, 0x8d68, 0x9d49, - 0x7e97, 0x6eb6, 0x5ed5, 0x4ef4, 0x3e13, 0x2e32, 0x1e51, 0x0e70, 0xff9f, 0xefbe, 0xdfdd, 0xcffc, 0xbf1b, 0xaf3a, - 0x9f59, 0x8f78, 0x9188, 0x81a9, 0xb1ca, 0xa1eb, 0xd10c, 0xc12d, 0xf14e, 0xe16f, 0x1080, 0x00a1, 0x30c2, 0x20e3, - 0x5004, 0x4025, 0x7046, 0x6067, 0x83b9, 0x9398, 0xa3fb, 0xb3da, 0xc33d, 0xd31c, 0xe37f, 0xf35e, 0x02b1, 0x1290, - 0x22f3, 0x32d2, 0x4235, 0x5214, 0x6277, 0x7256, 0xb5ea, 0xa5cb, 0x95a8, 0x8589, 0xf56e, 0xe54f, 0xd52c, 0xc50d, - 0x34e2, 0x24c3, 0x14a0, 0x0481, 0x7466, 0x6447, 0x5424, 0x4405, 0xa7db, 0xb7fa, 0x8799, 0x97b8, 0xe75f, 0xf77e, - 0xc71d, 0xd73c, 0x26d3, 0x36f2, 0x0691, 0x16b0, 0x6657, 0x7676, 0x4615, 0x5634, 0xd94c, 0xc96d, 0xf90e, 0xe92f, - 0x99c8, 0x89e9, 0xb98a, 0xa9ab, 0x5844, 0x4865, 0x7806, 0x6827, 0x18c0, 0x08e1, 0x3882, 0x28a3, 0xcb7d, 0xdb5c, - 0xeb3f, 0xfb1e, 0x8bf9, 0x9bd8, 0xabbb, 0xbb9a, 0x4a75, 0x5a54, 0x6a37, 0x7a16, 0x0af1, 0x1ad0, 0x2ab3, 0x3a92, - 0xfd2e, 0xed0f, 0xdd6c, 0xcd4d, 0xbdaa, 0xad8b, 0x9de8, 0x8dc9, 0x7c26, 0x6c07, 0x5c64, 0x4c45, 0x3ca2, 0x2c83, - 0x1ce0, 0x0cc1, 0xef1f, 0xff3e, 0xcf5d, 0xdf7c, 0xaf9b, 0xbfba, 0x8fd9, 0x9ff8, 0x6e17, 0x7e36, 0x4e55, 0x5e74, + 0x0000, 0x1021, 0x2042, 0x3063, 0x4084, 0x50a5, 0x60c6, 0x70e7, 0x8108, 0x9129, 0xa14a, 0xb16b, + 0xc18c, 0xd1ad, 0xe1ce, 0xf1ef, 0x1231, 0x0210, 0x3273, 0x2252, 0x52b5, 0x4294, 0x72f7, 0x62d6, + 0x9339, 0x8318, 0xb37b, 0xa35a, 0xd3bd, 0xc39c, 0xf3ff, 0xe3de, 0x2462, 0x3443, 0x0420, 0x1401, + 0x64e6, 0x74c7, 0x44a4, 0x5485, 0xa56a, 0xb54b, 0x8528, 0x9509, 0xe5ee, 0xf5cf, 0xc5ac, 0xd58d, + 0x3653, 0x2672, 0x1611, 0x0630, 0x76d7, 0x66f6, 0x5695, 0x46b4, 0xb75b, 0xa77a, 0x9719, 0x8738, + 0xf7df, 0xe7fe, 0xd79d, 0xc7bc, 0x48c4, 0x58e5, 0x6886, 0x78a7, 0x0840, 0x1861, 0x2802, 0x3823, + 0xc9cc, 0xd9ed, 0xe98e, 0xf9af, 0x8948, 0x9969, 0xa90a, 0xb92b, 0x5af5, 0x4ad4, 0x7ab7, 0x6a96, + 0x1a71, 0x0a50, 0x3a33, 0x2a12, 0xdbfd, 0xcbdc, 0xfbbf, 0xeb9e, 0x9b79, 0x8b58, 0xbb3b, 0xab1a, + 0x6ca6, 0x7c87, 0x4ce4, 0x5cc5, 0x2c22, 0x3c03, 0x0c60, 0x1c41, 0xedae, 0xfd8f, 0xcdec, 0xddcd, + 0xad2a, 0xbd0b, 0x8d68, 0x9d49, 0x7e97, 0x6eb6, 0x5ed5, 0x4ef4, 0x3e13, 0x2e32, 0x1e51, 0x0e70, + 0xff9f, 0xefbe, 0xdfdd, 0xcffc, 0xbf1b, 0xaf3a, 0x9f59, 0x8f78, 0x9188, 0x81a9, 0xb1ca, 0xa1eb, + 0xd10c, 0xc12d, 0xf14e, 0xe16f, 0x1080, 0x00a1, 0x30c2, 0x20e3, 0x5004, 0x4025, 0x7046, 0x6067, + 0x83b9, 0x9398, 0xa3fb, 0xb3da, 0xc33d, 0xd31c, 0xe37f, 0xf35e, 0x02b1, 0x1290, 0x22f3, 0x32d2, + 0x4235, 0x5214, 0x6277, 0x7256, 0xb5ea, 0xa5cb, 0x95a8, 0x8589, 0xf56e, 0xe54f, 0xd52c, 0xc50d, + 0x34e2, 0x24c3, 0x14a0, 0x0481, 0x7466, 0x6447, 0x5424, 0x4405, 0xa7db, 0xb7fa, 0x8799, 0x97b8, + 0xe75f, 0xf77e, 0xc71d, 0xd73c, 0x26d3, 0x36f2, 0x0691, 0x16b0, 0x6657, 0x7676, 0x4615, 0x5634, + 0xd94c, 0xc96d, 0xf90e, 0xe92f, 0x99c8, 0x89e9, 0xb98a, 0xa9ab, 0x5844, 0x4865, 0x7806, 0x6827, + 0x18c0, 0x08e1, 0x3882, 0x28a3, 0xcb7d, 0xdb5c, 0xeb3f, 0xfb1e, 0x8bf9, 0x9bd8, 0xabbb, 0xbb9a, + 0x4a75, 0x5a54, 0x6a37, 0x7a16, 0x0af1, 0x1ad0, 0x2ab3, 0x3a92, 0xfd2e, 0xed0f, 0xdd6c, 0xcd4d, + 0xbdaa, 0xad8b, 0x9de8, 0x8dc9, 0x7c26, 0x6c07, 0x5c64, 0x4c45, 0x3ca2, 0x2c83, 0x1ce0, 0x0cc1, + 0xef1f, 0xff3e, 0xcf5d, 0xdf7c, 0xaf9b, 0xbfba, 0x8fd9, 0x9ff8, 0x6e17, 0x7e36, 0x4e55, 0x5e74, 0x2e93, 0x3eb2, 0x0ed1, 0x1ef0, }; +uint16_t cx_crc16_update(uint16_t crc, const void *buf, size_t len) +{ +#define buffer ((const uint8_t *) buf) + uint32_t i; + uint8_t b; -uint16_t cx_crc16_update(uint16_t crc, const void *buf, size_t len) { -#define buffer ((const uint8_t *)buf) - uint32_t i; - uint8_t b; - - for (i = 0; i < len; i++) { - b = buffer[i]; - b = b ^ (crc >> 8); - crc = cx_ccitt[b] ^ (crc << 8); - } - return crc; + for (i = 0; i < len; i++) { + b = buffer[i]; + b = b ^ (crc >> 8); + crc = cx_ccitt[b] ^ (crc << 8); + } + return crc; } -uint16_t cx_crc16(const void *buf, size_t len) { - return cx_crc16_update(CX_CRC16_INIT, buf, len); +uint16_t cx_crc16(const void *buf, size_t len) +{ + return cx_crc16_update(CX_CRC16_INIT, buf, len); } -#endif // HAVE_CRC +#endif // HAVE_CRC diff --git a/lib_cxng/src/cx_crc32.c b/lib_cxng/src/cx_crc32.c index c7fc5821a..9b1c04bf9 100644 --- a/lib_cxng/src/cx_crc32.c +++ b/lib_cxng/src/cx_crc32.c @@ -1,20 +1,20 @@ /******************************************************************************* -* Ledger Nano S - Secure firmware -* (c) 2022 Ledger -* -* Licensed under the Apache License, Version 2.0 (the "License"); -* you may not use this file except in compliance with the License. -* You may obtain a copy of the License at -* -* http://www.apache.org/licenses/LICENSE-2.0 -* -* Unless required by applicable law or agreed to in writing, software -* distributed under the License is distributed on an "AS IS" BASIS, -* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -* See the License for the specific language governing permissions and -* limitations under the License. -********************************************************************************/ + * Ledger Nano S - Secure firmware + * (c) 2022 Ledger + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + ********************************************************************************/ #ifdef HAVE_CRC @@ -22,8 +22,9 @@ #include "cx_ram.h" // x^32 + x^26 + x^23 + x^22 + x^16 + x^12 + x^11 + x^10 + x^8 + x^7 + x^5 + x^4 + x^2 + x + 1 -uint32_t cx_crc32(const void *buf, size_t len) { - return cx_crc32_hw(buf, len); +uint32_t cx_crc32(const void *buf, size_t len) +{ + return cx_crc32_hw(buf, len); } -#endif // HAVE_CRC +#endif // HAVE_CRC diff --git a/lib_cxng/src/cx_ecdh.c b/lib_cxng/src/cx_ecdh.c index 11e753825..cf83da728 100644 --- a/lib_cxng/src/cx_ecdh.c +++ b/lib_cxng/src/cx_ecdh.c @@ -1,20 +1,20 @@ /******************************************************************************* -* Ledger Nano S - Secure firmware -* (c) 2022 Ledger -* -* Licensed under the Apache License, Version 2.0 (the "License"); -* you may not use this file except in compliance with the License. -* You may obtain a copy of the License at -* -* http://www.apache.org/licenses/LICENSE-2.0 -* -* Unless required by applicable law or agreed to in writing, software -* distributed under the License is distributed on an "AS IS" BASIS, -* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -* See the License for the specific language governing permissions and -* limitations under the License. -********************************************************************************/ + * Ledger Nano S - Secure firmware + * (c) 2022 Ledger + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT 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(HAVE_ECDH) || defined(HAVE_X25519) || defined(HAVE_X448) @@ -26,122 +26,126 @@ #if defined(HAVE_ECDH) cx_err_t cx_ecdh_no_throw(const cx_ecfp_private_key_t *key, - uint32_t mode, - const uint8_t * public_point, - size_t P_len, - uint8_t * secret, - size_t secret_len) { - size_t sz; - cx_curve_t curve; - cx_err_t error; - cx_ecpoint_t W; - - curve = key->curve; - CX_CHECK(cx_ecdomain_parameters_length(curve, &sz)); - - if (false + uint32_t mode, + const uint8_t *public_point, + size_t P_len, + uint8_t *secret, + size_t secret_len) +{ + size_t sz; + cx_curve_t curve; + cx_err_t error; + cx_ecpoint_t W; + + curve = key->curve; + CX_CHECK(cx_ecdomain_parameters_length(curve, &sz)); + + if (false #ifdef HAVE_ECC_WEIERSTRASS - || CX_CURVE_RANGE(curve, WEIERSTRASS) + || CX_CURVE_RANGE(curve, WEIERSTRASS) #endif #ifdef HAVE_ECC_MONTGOMERY - || CX_CURVE_RANGE(curve, MONTGOMERY) + || CX_CURVE_RANGE(curve, MONTGOMERY) #endif - ) { - if (P_len != (1 + sz * 2)) { - error = CX_INVALID_PARAMETER; - goto end; + ) { + if (P_len != (1 + sz * 2)) { + error = CX_INVALID_PARAMETER; + goto end; + } + if (!(((mode & CX_MASK_EC) == CX_ECDH_X) || ((mode & CX_MASK_EC) == CX_ECDH_POINT))) { + error = CX_INVALID_PARAMETER; + goto end; + } } - if (!(((mode & CX_MASK_EC) == CX_ECDH_X) || ((mode & CX_MASK_EC) == CX_ECDH_POINT))) { - error = CX_INVALID_PARAMETER; - goto end; + else { + error = INVALID_PARAMETER; + goto end; } - } - else { - error = INVALID_PARAMETER; - goto end; - } - - switch (mode & CX_MASK_EC) { - case CX_ECDH_POINT: - if (secret_len < P_len) { - error = INVALID_PARAMETER; - goto end; + + switch (mode & CX_MASK_EC) { + case CX_ECDH_POINT: + if (secret_len < P_len) { + error = INVALID_PARAMETER; + goto end; + } + break; + case CX_ECDH_X: + if (secret_len < sz) { + error = INVALID_PARAMETER; + goto end; + } + break; + default: + error = INVALID_PARAMETER; + goto end; + break; + } + + CX_CHECK(cx_bn_lock(sz, 0)); + CX_CHECK(cx_ecpoint_alloc(&W, curve)); + CX_CHECK(cx_ecpoint_init(&W, public_point + 1, sz, public_point + 1 + sz, sz)); + // Scalar multiplication with random projective coordinates and additive splitting + if (CX_CURVE_RANGE(curve, WEIERSTRASS)) { + CX_CHECK(cx_ecpoint_rnd_fixed_scalarmul(&W, key->d, key->d_len)); + } + else { + CX_CHECK(cx_ecpoint_rnd_scalarmul(&W, key->d, key->d_len)); } - break; - case CX_ECDH_X: - if (secret_len < sz) { - error = INVALID_PARAMETER; - goto end; + switch (mode & CX_MASK_EC) { + case CX_ECDH_POINT: + secret[0] = 0x04; + CX_CHECK(cx_ecpoint_export(&W, secret + 1, sz, secret + 1 + sz, sz)); + break; + case CX_ECDH_X: + CX_CHECK(cx_ecpoint_export(&W, secret, sz, NULL, 0)); + break; } - break; - default: - error = INVALID_PARAMETER; - goto end; - break; - } - - CX_CHECK(cx_bn_lock(sz, 0)); - CX_CHECK(cx_ecpoint_alloc(&W, curve)); - CX_CHECK(cx_ecpoint_init(&W, public_point + 1, sz, public_point + 1 + sz, sz)); - // Scalar multiplication with random projective coordinates and additive splitting - if (CX_CURVE_RANGE(curve, WEIERSTRASS)) { - CX_CHECK(cx_ecpoint_rnd_fixed_scalarmul(&W, key->d, key->d_len)); - } else { - CX_CHECK(cx_ecpoint_rnd_scalarmul(&W, key->d, key->d_len)); - } - switch (mode & CX_MASK_EC) { - case CX_ECDH_POINT: - secret[0] = 0x04; - CX_CHECK(cx_ecpoint_export(&W, secret + 1, sz, secret + 1 + sz, sz)); - break; - case CX_ECDH_X: - CX_CHECK(cx_ecpoint_export(&W, secret, sz, NULL, 0)); - break; - } - - end: - cx_bn_unlock(); - return error; + +end: + cx_bn_unlock(); + return error; } -#endif // HAVE_ECDH +#endif // HAVE_ECDH #if defined(HAVE_X25519) -cx_err_t cx_x25519(uint8_t *u, const uint8_t *k, size_t k_len) { - cx_bn_t bn_u; - size_t domain_length; - cx_err_t error; - - CX_CHECK(cx_ecdomain_parameters_length(CX_CURVE_Curve25519, &domain_length)); - CX_CHECK(cx_bn_lock(domain_length, 0)); - CX_CHECK(cx_bn_alloc(&bn_u, domain_length)); - CX_CHECK(cx_bn_init(bn_u, u, domain_length)); - CX_CHECK(cx_ecpoint_x25519(bn_u, k, k_len)); - CX_CHECK(cx_bn_export(bn_u, u, domain_length)); - - end: +cx_err_t cx_x25519(uint8_t *u, const uint8_t *k, size_t k_len) +{ + cx_bn_t bn_u; + size_t domain_length; + cx_err_t error; + + CX_CHECK(cx_ecdomain_parameters_length(CX_CURVE_Curve25519, &domain_length)); + CX_CHECK(cx_bn_lock(domain_length, 0)); + CX_CHECK(cx_bn_alloc(&bn_u, domain_length)); + CX_CHECK(cx_bn_init(bn_u, u, domain_length)); + CX_CHECK(cx_ecpoint_x25519(bn_u, k, k_len)); + CX_CHECK(cx_bn_export(bn_u, u, domain_length)); + +end: cx_bn_unlock(); return error; } -#endif // HAVE_X25519 +#endif // HAVE_X25519 #if defined(HAVE_X448) -cx_err_t cx_x448(uint8_t *u, const uint8_t *k, size_t k_len) { - cx_bn_t bn_u; - size_t domain_length; - cx_err_t error; - - CX_CHECK(cx_ecdomain_parameters_length(CX_CURVE_Curve448, &domain_length)); - CX_CHECK(cx_bn_lock(domain_length, 0)); - CX_CHECK(cx_bn_alloc(&bn_u, domain_length)); - CX_CHECK(cx_bn_init(bn_u, u, domain_length)); - CX_CHECK(cx_ecpoint_x448(bn_u, k, k_len)); - CX_CHECK(cx_bn_export(bn_u, u, domain_length)); - - end: +cx_err_t cx_x448(uint8_t *u, const uint8_t *k, size_t k_len) +{ + cx_bn_t bn_u; + size_t domain_length; + cx_err_t error; + + CX_CHECK(cx_ecdomain_parameters_length(CX_CURVE_Curve448, &domain_length)); + CX_CHECK(cx_bn_lock(domain_length, 0)); + CX_CHECK(cx_bn_alloc(&bn_u, domain_length)); + CX_CHECK(cx_bn_init(bn_u, u, domain_length)); + CX_CHECK(cx_ecpoint_x448(bn_u, k, k_len)); + CX_CHECK(cx_bn_export(bn_u, u, domain_length)); + +end: cx_bn_unlock(); return error; } -#endif // HAVE_X448 +#endif // HAVE_X448 -#endif // HAVE_ECDH || HAVE_X25519 || HAVE_X448 +#endif // HAVE_ECDH || HAVE_X25519 || HAVE_X448 diff --git a/lib_cxng/src/cx_ecdsa.c b/lib_cxng/src/cx_ecdsa.c index a363ce9d5..0c443176e 100644 --- a/lib_cxng/src/cx_ecdsa.c +++ b/lib_cxng/src/cx_ecdsa.c @@ -1,20 +1,20 @@ /******************************************************************************* -* Ledger Nano S - Secure firmware -* (c) 2022 Ledger -* -* Licensed under the Apache License, Version 2.0 (the "License"); -* you may not use this file except in compliance with the License. -* You may obtain a copy of the License at -* -* http://www.apache.org/licenses/LICENSE-2.0 -* -* Unless required by applicable law or agreed to in writing, software -* distributed under the License is distributed on an "AS IS" BASIS, -* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -* See the License for the specific language governing permissions and -* limitations under the License. -********************************************************************************/ + * Ledger Nano S - Secure firmware + * (c) 2022 Ledger + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + ********************************************************************************/ #ifdef HAVE_ECDSA @@ -28,49 +28,60 @@ #include -static cx_err_t truernd(uint8_t *rnd, cx_curve_t cv) { - cx_bn_t r, t, n; - uint8_t domain_order[CX_ECDSA_MAX_ORDER_LEN]; - size_t domain_length; - cx_err_t error; - - CX_CHECK(cx_ecdomain_parameters_length(cv, &domain_length)); - CX_CHECK(cx_ecdomain_parameter(cv, CX_CURVE_PARAM_Order, domain_order, sizeof(domain_order))); - - CX_CHECK(cx_bn_lock(domain_length, 0)); - CX_CHECK(cx_bn_alloc(&r, domain_length)); - CX_CHECK(cx_bn_alloc(&t, 2 * domain_length)); - CX_CHECK(cx_bn_alloc_init(&n, domain_length, domain_order, domain_length)); - CX_CHECK(cx_bn_rand(t)); - CX_CHECK(cx_bn_reduce(r, t, n)); - CX_CHECK(cx_bn_export(r, rnd, domain_length)); - cx_bn_unlock(); - - end: - return error; +static cx_err_t truernd(uint8_t *rnd, cx_curve_t cv) +{ + cx_bn_t r, t, n; + uint8_t domain_order[CX_ECDSA_MAX_ORDER_LEN]; + size_t domain_length; + cx_err_t error; + + CX_CHECK(cx_ecdomain_parameters_length(cv, &domain_length)); + CX_CHECK(cx_ecdomain_parameter(cv, CX_CURVE_PARAM_Order, domain_order, sizeof(domain_order))); + + CX_CHECK(cx_bn_lock(domain_length, 0)); + CX_CHECK(cx_bn_alloc(&r, domain_length)); + CX_CHECK(cx_bn_alloc(&t, 2 * domain_length)); + CX_CHECK(cx_bn_alloc_init(&n, domain_length, domain_order, domain_length)); + CX_CHECK(cx_bn_rand(t)); + CX_CHECK(cx_bn_reduce(r, t, n)); + CX_CHECK(cx_bn_export(r, rnd, domain_length)); + cx_bn_unlock(); + +end: + return error; } -static cx_err_t rfcrnd(uint8_t *rnd, uint32_t skip, - cx_curve_t cv, +static cx_err_t rfcrnd(uint8_t *rnd, + uint32_t skip, + cx_curve_t cv, const cx_ecfp_private_key_t *key, - cx_md_t hashID, const uint8_t *hash, size_t hash_len) { - uint8_t domain_order[CX_ECDSA_MAX_ORDER_LEN]; - size_t domain_length; - cx_err_t error; - - CX_CHECK(cx_ecdomain_parameters_length(cv, &domain_length)); - CX_CHECK(cx_ecdomain_parameter(cv, CX_CURVE_PARAM_Order, domain_order, sizeof(domain_order))); - - CX_CHECK(cx_rng_rfc6979_init(&G_cx.rfc6979, hashID, key->d, key->d_len, hash, hash_len, domain_order, domain_length/*, NULL, 0*/)); - skip++; - for (uint32_t i = 0; id, + key->d_len, + hash, + hash_len, + domain_order, + domain_length /*, NULL, 0*/)); + skip++; + for (uint32_t i = 0; i < skip; i++) { + CX_CHECK(cx_rng_rfc6979_next(&G_cx.rfc6979, rnd, domain_length)); + } +end: + return error; +} // This function is used to convert the incoming hash into its bn // representation, depending on its length compared to the domain's @@ -78,357 +89,363 @@ static cx_err_t rfcrnd(uint8_t *rnd, uint32_t skip, // The v parameter must already point to an initialized RAM area, of length // domain_length. static cx_err_t initialize_hash(const uint8_t *hash, - cx_bn_t v, - size_t domain_bit_length, - size_t hash_length, - size_t domain_length) { - cx_err_t error; - - // If the hash length is greater than the domain length, we only - // consider the 'domain bit length' leftmost bits of the hash - // for the operation. - CX_CHECK(cx_bn_init(v, hash, MIN(hash_length, domain_length))); - - if (domain_bit_length < hash_length * 8) { - // We shift the hash if necessary. - if (domain_bit_length % 8) { - CX_CHECK(cx_bn_shr(v, 8 - (domain_bit_length % 8))); + cx_bn_t v, + size_t domain_bit_length, + size_t hash_length, + size_t domain_length) +{ + cx_err_t error; + + // If the hash length is greater than the domain length, we only + // consider the 'domain bit length' leftmost bits of the hash + // for the operation. + CX_CHECK(cx_bn_init(v, hash, MIN(hash_length, domain_length))); + + if (domain_bit_length < hash_length * 8) { + // We shift the hash if necessary. + if (domain_bit_length % 8) { + CX_CHECK(cx_bn_shr(v, 8 - (domain_bit_length % 8))); + } } - } end: - return error; + return error; } /* ----------------------------------------------------------------------- */ /* */ /* ----------------------------------------------------------------------- */ cx_err_t cx_ecdsa_sign_no_throw(const cx_ecfp_private_key_t *key, - uint32_t mode, - cx_md_t hashID, - const uint8_t * hash, - size_t hash_len, - uint8_t * sig, - size_t * sig_len, - uint32_t * info) { - #ifndef HAVE_RNG_RFC6979 - (void)hashID; - #endif + uint32_t mode, + cx_md_t hashID, + const uint8_t *hash, + size_t hash_len, + uint8_t *sig, + size_t *sig_len, + uint32_t *info) +{ +#ifndef HAVE_RNG_RFC6979 + (void) hashID; +#endif #define CX_MAX_TRIES 100 - cx_err_t error; - uint32_t volatile out_sig_len = 0; - size_t domain_length; - size_t domain_bit_length; - cx_bn_t r, s; - int diff; - union { - struct { - uint32_t _tries; - uint8_t _rnd[CX_ECDSA_MAX_ORDER_LEN]; - cx_ecpoint_t _Q; - cx_bn_t _n, _t, _t1, _t2, _v; - }; - uint8_t _rs[CX_ECDSA_MAX_ORDER_LEN * 2]; - } u; - #define tries u._tries - #define rnd u._rnd - #define Q u._Q - #define n u._n - #define t u._t - #define t1 u._t1 - #define t2 u._t2 - #define v u._v - #define rs u._rs - - // get dom - CX_CHECK(cx_ecdomain_parameters_length(key->curve, &domain_length)); - CX_CHECK(cx_ecdomain_size(key->curve, &domain_bit_length)); - - if (!CX_CURVE_RANGE(key->curve, WEIERSTRASS) || - *sig_len < 6 + 2 * (domain_length + 1) || - key->d_len != domain_length) { - error = CX_INVALID_PARAMETER; - goto end; - } - - if (info) { - *info = 0; - } - - out_sig_len = *sig_len; - - // generate random - tries = 0; - RETRY: - if (tries == CX_MAX_TRIES) { - out_sig_len = 0; - error = CX_INTERNAL_ERROR; - goto end; - } - - switch (mode & CX_MASK_RND) { - default: - error = CX_INVALID_PARAMETER; - goto end; - - case CX_RND_PROVIDED: - if (tries) { - out_sig_len = 0; - error = CX_INTERNAL_ERROR; - goto end; + cx_err_t error; + uint32_t volatile out_sig_len = 0; + size_t domain_length; + size_t domain_bit_length; + cx_bn_t r, s; + int diff; + union { + struct { + uint32_t _tries; + uint8_t _rnd[CX_ECDSA_MAX_ORDER_LEN]; + cx_ecpoint_t _Q; + cx_bn_t _n, _t, _t1, _t2, _v; + }; + uint8_t _rs[CX_ECDSA_MAX_ORDER_LEN * 2]; + } u; +#define tries u._tries +#define rnd u._rnd +#define Q u._Q +#define n u._n +#define t u._t +#define t1 u._t1 +#define t2 u._t2 +#define v u._v +#define rs u._rs + + // get dom + CX_CHECK(cx_ecdomain_parameters_length(key->curve, &domain_length)); + CX_CHECK(cx_ecdomain_size(key->curve, &domain_bit_length)); + + if (!CX_CURVE_RANGE(key->curve, WEIERSTRASS) || *sig_len < 6 + 2 * (domain_length + 1) + || key->d_len != domain_length) { + error = CX_INVALID_PARAMETER; + goto end; + } + + if (info) { + *info = 0; + } + + out_sig_len = *sig_len; + + // generate random + tries = 0; +RETRY: + if (tries == CX_MAX_TRIES) { + out_sig_len = 0; + error = CX_INTERNAL_ERROR; + goto end; } - memmove(rnd, sig, domain_length); - break; - case CX_RND_TRNG: - CX_CHECK(truernd(rnd, key->curve)); - break; + switch (mode & CX_MASK_RND) { + default: + error = CX_INVALID_PARAMETER; + goto end; + + case CX_RND_PROVIDED: + if (tries) { + out_sig_len = 0; + error = CX_INTERNAL_ERROR; + goto end; + } + memmove(rnd, sig, domain_length); + break; + + case CX_RND_TRNG: + CX_CHECK(truernd(rnd, key->curve)); + break; #ifdef HAVE_RNG_RFC6979 - case CX_RND_RFC6979: - // If the hash length is greater than the domain length, we only consider - // the domain length's leftmost bytes of the hash for the operation. - // This optimisation works so long as (hash_len - domain_length) is a - // multiple of 8, when hash_len > domain_length. Otherwise, the hash - // needs to be shifted by (hash_len - domain_length) bits to fit into - // domain_length bytes. - CX_CHECK(rfcrnd(rnd, tries, key->curve, key, hashID, hash, MIN(hash_len, domain_length))); - break; -#endif //HAVE_RNG_RFC6979 - } - tries++; - - // compute the sig - CX_CHECK(cx_bn_lock(domain_length, 0)); - - // --> compute Q = k.G - CX_CHECK(cx_ecpoint_alloc(&Q, key->curve)); - CX_CHECK(cx_ecdomain_generator_bn(key->curve, &Q)); + case CX_RND_RFC6979: + // If the hash length is greater than the domain length, we only consider + // the domain length's leftmost bytes of the hash for the operation. + // This optimisation works so long as (hash_len - domain_length) is a + // multiple of 8, when hash_len > domain_length. Otherwise, the hash + // needs to be shifted by (hash_len - domain_length) bits to fit into + // domain_length bytes. + CX_CHECK( + rfcrnd(rnd, tries, key->curve, key, hashID, hash, MIN(hash_len, domain_length))); + break; +#endif // HAVE_RNG_RFC6979 + } + tries++; + + // compute the sig + CX_CHECK(cx_bn_lock(domain_length, 0)); + + // --> compute Q = k.G + CX_CHECK(cx_ecpoint_alloc(&Q, key->curve)); + CX_CHECK(cx_ecdomain_generator_bn(key->curve, &Q)); #ifdef HAVE_FIXED_SCALAR_LENGTH - // Additive splitting with random projective coordinates - // The length of the scalar is fixed to not leak information - CX_CHECK(cx_ecpoint_rnd_fixed_scalarmul(&Q, rnd, domain_length)); + // Additive splitting with random projective coordinates + // The length of the scalar is fixed to not leak information + CX_CHECK(cx_ecpoint_rnd_fixed_scalarmul(&Q, rnd, domain_length)); #else - CX_CHECK(cx_ecpoint_rnd_scalarmul(&Q, rnd, domain_length)); -#endif // HAVE_FIXED_SCALAR_LENGTH - - bool odd; - CX_CHECK(cx_bn_is_odd(Q.y, &odd)); - - // load order - CX_CHECK(cx_bn_alloc(&n, domain_length)); - CX_CHECK(cx_ecdomain_parameter_bn(key->curve, CX_CURVE_PARAM_Order, n)); - - // compute r - CX_CHECK(cx_bn_alloc(&r, domain_length)); - CX_CHECK(cx_ecpoint_export_bn(&Q, &r, NULL)); - CX_CHECK(cx_ecpoint_destroy(&Q)); - CX_CHECK(cx_bn_cmp(r, n, &diff)); - if (diff >= 0) { - CX_CHECK_IGNORE_CARRY(cx_bn_sub(r, r, n)); - if (info) { - *info |= CX_ECCINFO_xGTn; + CX_CHECK(cx_ecpoint_rnd_scalarmul(&Q, rnd, domain_length)); +#endif // HAVE_FIXED_SCALAR_LENGTH + + bool odd; + CX_CHECK(cx_bn_is_odd(Q.y, &odd)); + + // load order + CX_CHECK(cx_bn_alloc(&n, domain_length)); + CX_CHECK(cx_ecdomain_parameter_bn(key->curve, CX_CURVE_PARAM_Order, n)); + + // compute r + CX_CHECK(cx_bn_alloc(&r, domain_length)); + CX_CHECK(cx_ecpoint_export_bn(&Q, &r, NULL)); + CX_CHECK(cx_ecpoint_destroy(&Q)); + CX_CHECK(cx_bn_cmp(r, n, &diff)); + if (diff >= 0) { + CX_CHECK_IGNORE_CARRY(cx_bn_sub(r, r, n)); + if (info) { + *info |= CX_ECCINFO_xGTn; + } } - } - - //check r non zero - CX_CHECK(cx_bn_cmp_u32(r, 0, &diff)); - if (diff == 0) { - goto RETRY; - } - - //some allocs - CX_CHECK(cx_bn_alloc(&s, domain_length)); - CX_CHECK(cx_bn_alloc(&t, domain_length)); - CX_CHECK(cx_bn_alloc(&v, domain_length)); - CX_CHECK(cx_bn_alloc(&t1, domain_length)); - CX_CHECK(cx_bn_alloc(&t2, domain_length)); - - // compute s = kinv(h+d.x) - // - // t random, 0 <= t < n - // v = d - t - // u = h + (d-t)*x +t*x = h + v*x + t*x - // s = k_inv*u - // - - CX_CHECK(cx_bn_rng(t, n)); - CX_CHECK(cx_bn_init(t1, key->d, key->d_len)); - CX_CHECK(cx_bn_mod_sub(v, t1, t, n)); // v - CX_CHECK(cx_bn_mod_mul(t2, v, r, n)); // v.x - CX_CHECK(cx_bn_mod_mul(t1, t, r, n)); // t.x - - CX_CHECK(initialize_hash(hash, v, domain_bit_length, hash_len, domain_length)); - // v = h (or domain bit length's leftmost bits of h) - CX_CHECK(cx_bn_mod_add(v, v, t1, n)); // v += t.x - CX_CHECK(cx_bn_mod_add(v, v, t2, n)); // v += v.x - CX_CHECK(cx_bn_init(t1, rnd, domain_length)); // k - CX_CHECK(cx_bn_mod_invert_nprime(t2, t1, n)); // k_inv - CX_CHECK(cx_bn_mod_mul(s, v, t2, n)); // s = k_inv*u - //check s non zero - CX_CHECK(cx_bn_cmp_u32(s, 0, &diff)); - if (diff == 0) { - goto RETRY; - } - - // "Sainte Canonisation" - if ((mode & CX_NO_CANONICAL) == 0) { - // if s > order/2, s = -s = order-s - CX_CHECK_IGNORE_CARRY(cx_bn_sub(t1, n, s)); - CX_CHECK(cx_bn_shr(n, 1)); - CX_CHECK(cx_bn_cmp(s, n, &diff)); - if (diff > 0) { - CX_CHECK(cx_bn_copy(s, t1)); - odd = !odd; + + // check r non zero + CX_CHECK(cx_bn_cmp_u32(r, 0, &diff)); + if (diff == 0) { + goto RETRY; + } + + // some allocs + CX_CHECK(cx_bn_alloc(&s, domain_length)); + CX_CHECK(cx_bn_alloc(&t, domain_length)); + CX_CHECK(cx_bn_alloc(&v, domain_length)); + CX_CHECK(cx_bn_alloc(&t1, domain_length)); + CX_CHECK(cx_bn_alloc(&t2, domain_length)); + + // compute s = kinv(h+d.x) + // + // t random, 0 <= t < n + // v = d - t + // u = h + (d-t)*x +t*x = h + v*x + t*x + // s = k_inv*u + // + + CX_CHECK(cx_bn_rng(t, n)); + CX_CHECK(cx_bn_init(t1, key->d, key->d_len)); + CX_CHECK(cx_bn_mod_sub(v, t1, t, n)); // v + CX_CHECK(cx_bn_mod_mul(t2, v, r, n)); // v.x + CX_CHECK(cx_bn_mod_mul(t1, t, r, n)); // t.x + + CX_CHECK(initialize_hash(hash, v, domain_bit_length, hash_len, domain_length)); + // v = h (or domain bit length's leftmost bits of h) + CX_CHECK(cx_bn_mod_add(v, v, t1, n)); // v += t.x + CX_CHECK(cx_bn_mod_add(v, v, t2, n)); // v += v.x + CX_CHECK(cx_bn_init(t1, rnd, domain_length)); // k + CX_CHECK(cx_bn_mod_invert_nprime(t2, t1, n)); // k_inv + CX_CHECK(cx_bn_mod_mul(s, v, t2, n)); // s = k_inv*u + // check s non zero + CX_CHECK(cx_bn_cmp_u32(s, 0, &diff)); + if (diff == 0) { + goto RETRY; + } + + // "Sainte Canonisation" + if ((mode & CX_NO_CANONICAL) == 0) { + // if s > order/2, s = -s = order-s + CX_CHECK_IGNORE_CARRY(cx_bn_sub(t1, n, s)); + CX_CHECK(cx_bn_shr(n, 1)); + CX_CHECK(cx_bn_cmp(s, n, &diff)); + if (diff > 0) { + CX_CHECK(cx_bn_copy(s, t1)); + odd = !odd; + } } - } - - //WARN: from here only args and locals out_sig_len, r, s, rs, domain_length are valid - - CX_CHECK(cx_bn_export(r, rs, domain_length)); - CX_CHECK(cx_bn_export(s, rs + domain_length, domain_length)); - - // --> build the signature in TLV: T L T L r T L s - // 30 ll 02 ll X1 02 ll Y1 - // r,s == X2,Y2 - out_sig_len = cx_ecfp_encode_sig_der(sig, out_sig_len, rs, domain_length, rs + domain_length, domain_length); - if (info) { - *info |= odd ? CX_ECCINFO_PARITY_ODD : 0; - } - - end: - *sig_len = out_sig_len; - cx_bn_unlock(); - return error; - - #undef CX_MAX_TRIES - #undef tries - #undef rnd - #undef Q - #undef n - #undef t - #undef t1 - #undef t2 - #undef v - #undef rs + + // WARN: from here only args and locals out_sig_len, r, s, rs, domain_length are valid + + CX_CHECK(cx_bn_export(r, rs, domain_length)); + CX_CHECK(cx_bn_export(s, rs + domain_length, domain_length)); + + // --> build the signature in TLV: T L T L r T L s + // 30 ll 02 ll X1 02 ll Y1 + // r,s == X2,Y2 + out_sig_len = cx_ecfp_encode_sig_der( + sig, out_sig_len, rs, domain_length, rs + domain_length, domain_length); + if (info) { + *info |= odd ? CX_ECCINFO_PARITY_ODD : 0; + } + +end: + *sig_len = out_sig_len; + cx_bn_unlock(); + return error; + +#undef CX_MAX_TRIES +#undef tries +#undef rnd +#undef Q +#undef n +#undef t +#undef t1 +#undef t2 +#undef v +#undef rs } /* ----------------------------------------------------------------------- */ /* */ /* ----------------------------------------------------------------------- */ bool cx_ecdsa_verify_no_throw(const cx_ecfp_public_key_t *key, - const uint8_t * hash, - size_t hash_len, - const uint8_t * sig, - size_t sig_len) { - bool verified; - size_t domain_length, domain_bit_length; - cx_bn_t c, n, r, s, u1, u2, h; - cx_ecpoint_t R, Q, G; - cx_err_t error; - int diff; - bool is_infinite; - - verified = false; - - CX_CHECK(cx_ecdomain_parameters_length(key->curve, &domain_length)); - CX_CHECK(cx_ecdomain_size(key->curve, &domain_bit_length)); - - if (!CX_CURVE_RANGE(key->curve, WEIERSTRASS) || key->W_len != 1 + 2 * domain_length) { - error = CX_INVALID_PARAMETER; - goto end; - } - - // verify - //. check sig format - if (hash_len > (8 + 2 * domain_length)) { - error = CX_INVALID_PARAMETER; - goto end; - } - - const uint8_t *sig_r, *sig_s; - size_t sig_rlen, sig_slen; - - // decode - if (!cx_ecfp_decode_sig_der(sig, sig_len, domain_length, &sig_r, &sig_rlen, &sig_s, &sig_slen)) { - error = CX_INVALID_PARAMETER; - goto end; - } - - // setup - CX_CHECK(cx_bn_lock(domain_length, 0)); - CX_CHECK(cx_bn_alloc(&n, domain_length)); - CX_CHECK(cx_ecdomain_parameter_bn(key->curve, CX_CURVE_PARAM_Order, n)); - CX_CHECK(cx_bn_alloc_init(&r, domain_length, sig_r, sig_rlen)); - CX_CHECK(cx_bn_alloc_init(&s, domain_length, sig_s, sig_slen)); - CX_CHECK(cx_bn_alloc(&h, domain_length)); - CX_CHECK(initialize_hash(hash, h, domain_bit_length, hash_len, domain_length)); - CX_CHECK(cx_bn_alloc(&u1, domain_length)); - CX_CHECK(cx_bn_alloc(&u2, domain_length)); - CX_CHECK(cx_bn_alloc(&c, domain_length)); - - // 1 check 0 < r <= N-1 and 0 < s <= N-1 - CX_CHECK(cx_bn_set_u32(u2, 0)); - CX_CHECK(cx_bn_cmp(r, u2, &diff)); - if (diff == 0) { - goto end; - } - CX_CHECK(cx_bn_cmp(r, n, &diff)); - if (diff >= 0) { - goto end; - } - CX_CHECK(cx_bn_cmp(s, u2, &diff)); - if (diff == 0) { - goto end; - } - CX_CHECK(cx_bn_cmp(s, n, &diff)); - if (diff >= 0) { - goto end; - } - - // 2 verify r/s - //.compute c = inv(s) mod N ; - CX_CHECK(cx_bn_mod_invert_nprime(c, s, n)); - //.compute u1 = hash*c mod N * - CX_CHECK(cx_bn_mod_mul(u1, h, c, n)); - //.compute u2 = r*c mod N - CX_CHECK(cx_bn_mod_mul(u2, r, c, n)); - // uG+vQ - CX_CHECK(cx_bn_destroy(&h)); - CX_CHECK(cx_bn_destroy(&c)); - CX_CHECK(cx_bn_destroy(&s)); - CX_CHECK(cx_ecpoint_alloc(&G, key->curve)); - CX_CHECK(cx_ecdomain_generator_bn(key->curve, &G)); - CX_CHECK(cx_ecpoint_alloc(&Q, key->curve)); - CX_CHECK(cx_ecpoint_init(&Q, &key->W[1], domain_length, &key->W[1 + domain_length], domain_length)); - - CX_CHECK(cx_ecpoint_alloc(&R,key->curve)); - - // Double scalar multiplication using Straus-Shamir 's trick - CX_CHECK(cx_ecpoint_double_scalarmul_bn(&R, &G , &Q , u1, u2)); - - // Check if R is infinite point - CX_CHECK(cx_ecpoint_is_at_infinity(&R, &is_infinite)); - if (is_infinite) { - goto end; - } - //.compute v = x1 mod N - CX_CHECK(cx_ecpoint_export_bn(&R, &u1, NULL)); - CX_CHECK(cx_bn_reduce(u2, u1, n)); - //.verify value - CX_CHECK(cx_bn_cmp(u2, r, &diff)); - if (diff) { - goto end; - } - - verified = true; - - end: - cx_bn_unlock(); - return (error == CX_OK) && verified; + const uint8_t *hash, + size_t hash_len, + const uint8_t *sig, + size_t sig_len) +{ + bool verified; + size_t domain_length, domain_bit_length; + cx_bn_t c, n, r, s, u1, u2, h; + cx_ecpoint_t R, Q, G; + cx_err_t error; + int diff; + bool is_infinite; + + verified = false; + + CX_CHECK(cx_ecdomain_parameters_length(key->curve, &domain_length)); + CX_CHECK(cx_ecdomain_size(key->curve, &domain_bit_length)); + + if (!CX_CURVE_RANGE(key->curve, WEIERSTRASS) || key->W_len != 1 + 2 * domain_length) { + error = CX_INVALID_PARAMETER; + goto end; + } + + // verify + //. check sig format + if (hash_len > (8 + 2 * domain_length)) { + error = CX_INVALID_PARAMETER; + goto end; + } + + const uint8_t *sig_r, *sig_s; + size_t sig_rlen, sig_slen; + + // decode + if (!cx_ecfp_decode_sig_der( + sig, sig_len, domain_length, &sig_r, &sig_rlen, &sig_s, &sig_slen)) { + error = CX_INVALID_PARAMETER; + goto end; + } + + // setup + CX_CHECK(cx_bn_lock(domain_length, 0)); + CX_CHECK(cx_bn_alloc(&n, domain_length)); + CX_CHECK(cx_ecdomain_parameter_bn(key->curve, CX_CURVE_PARAM_Order, n)); + CX_CHECK(cx_bn_alloc_init(&r, domain_length, sig_r, sig_rlen)); + CX_CHECK(cx_bn_alloc_init(&s, domain_length, sig_s, sig_slen)); + CX_CHECK(cx_bn_alloc(&h, domain_length)); + CX_CHECK(initialize_hash(hash, h, domain_bit_length, hash_len, domain_length)); + CX_CHECK(cx_bn_alloc(&u1, domain_length)); + CX_CHECK(cx_bn_alloc(&u2, domain_length)); + CX_CHECK(cx_bn_alloc(&c, domain_length)); + + // 1 check 0 < r <= N-1 and 0 < s <= N-1 + CX_CHECK(cx_bn_set_u32(u2, 0)); + CX_CHECK(cx_bn_cmp(r, u2, &diff)); + if (diff == 0) { + goto end; + } + CX_CHECK(cx_bn_cmp(r, n, &diff)); + if (diff >= 0) { + goto end; + } + CX_CHECK(cx_bn_cmp(s, u2, &diff)); + if (diff == 0) { + goto end; + } + CX_CHECK(cx_bn_cmp(s, n, &diff)); + if (diff >= 0) { + goto end; + } + + // 2 verify r/s + //.compute c = inv(s) mod N ; + CX_CHECK(cx_bn_mod_invert_nprime(c, s, n)); + //.compute u1 = hash*c mod N * + CX_CHECK(cx_bn_mod_mul(u1, h, c, n)); + //.compute u2 = r*c mod N + CX_CHECK(cx_bn_mod_mul(u2, r, c, n)); + // uG+vQ + CX_CHECK(cx_bn_destroy(&h)); + CX_CHECK(cx_bn_destroy(&c)); + CX_CHECK(cx_bn_destroy(&s)); + CX_CHECK(cx_ecpoint_alloc(&G, key->curve)); + CX_CHECK(cx_ecdomain_generator_bn(key->curve, &G)); + CX_CHECK(cx_ecpoint_alloc(&Q, key->curve)); + CX_CHECK( + cx_ecpoint_init(&Q, &key->W[1], domain_length, &key->W[1 + domain_length], domain_length)); + + CX_CHECK(cx_ecpoint_alloc(&R, key->curve)); + + // Double scalar multiplication using Straus-Shamir 's trick + CX_CHECK(cx_ecpoint_double_scalarmul_bn(&R, &G, &Q, u1, u2)); + + // Check if R is infinite point + CX_CHECK(cx_ecpoint_is_at_infinity(&R, &is_infinite)); + if (is_infinite) { + goto end; + } + //.compute v = x1 mod N + CX_CHECK(cx_ecpoint_export_bn(&R, &u1, NULL)); + CX_CHECK(cx_bn_reduce(u2, u1, n)); + //.verify value + CX_CHECK(cx_bn_cmp(u2, r, &diff)); + if (diff) { + goto end; + } + + verified = true; + +end: + cx_bn_unlock(); + return (error == CX_OK) && verified; } -#endif // HAVE_ECDSA +#endif // HAVE_ECDSA diff --git a/lib_cxng/src/cx_ecdsa.h b/lib_cxng/src/cx_ecdsa.h index 60caf7a22..000c62658 100644 --- a/lib_cxng/src/cx_ecdsa.h +++ b/lib_cxng/src/cx_ecdsa.h @@ -1,27 +1,27 @@ /******************************************************************************* -* Ledger Nano S - Secure firmware -* (c) 2022 Ledger -* -* Licensed under the Apache License, Version 2.0 (the "License"); -* you may not use this file except in compliance with the License. -* You may obtain a copy of the License at -* -* http://www.apache.org/licenses/LICENSE-2.0 -* -* Unless required by applicable law or agreed to in writing, software -* distributed under the License is distributed on an "AS IS" BASIS, -* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -* See the License for the specific language governing permissions and -* limitations under the License. -********************************************************************************/ + * Ledger Nano S - Secure firmware + * (c) 2022 Ledger + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + ********************************************************************************/ #ifdef HAVE_ECDSA #ifndef CX_ECDSA_H #define CX_ECDSA_H -/* In the supported elliptic curves, the order has at most 521 bits (with NIST P-521 a.k.a. secp521r1). - * The next multiple of 8 is 528 = 66*8. +/* In the supported elliptic curves, the order has at most 521 bits (with NIST P-521 a.k.a. + * secp521r1). The next multiple of 8 is 528 = 66*8. */ #define CX_ECDSA_MAX_ORDER_LEN 66 diff --git a/lib_cxng/src/cx_ecfp.c b/lib_cxng/src/cx_ecfp.c index e248872b9..65a55b0d0 100644 --- a/lib_cxng/src/cx_ecfp.c +++ b/lib_cxng/src/cx_ecfp.c @@ -1,20 +1,20 @@ /******************************************************************************* -* Ledger Nano S - Secure firmware -* (c) 2022 Ledger -* -* Licensed under the Apache License, Version 2.0 (the "License"); -* you may not use this file except in compliance with the License. -* You may obtain a copy of the License at -* -* http://www.apache.org/licenses/LICENSE-2.0 -* -* Unless required by applicable law or agreed to in writing, software -* distributed under the License is distributed on an "AS IS" BASIS, -* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -* See the License for the specific language governing permissions and -* limitations under the License. -********************************************************************************/ + * Ledger Nano S - Secure firmware + * (c) 2022 Ledger + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + ********************************************************************************/ #ifdef HAVE_ECC @@ -26,7 +26,6 @@ #include - /* ========================================================================= */ /* ========================================================================= */ /* === APIs === */ @@ -36,591 +35,638 @@ /* ----------------------------------------------------------------------- */ /* */ /* ----------------------------------------------------------------------- */ -cx_err_t cx_ecfp_init_private_key_no_throw(cx_curve_t curve, const uint8_t *raw_key, size_t key_len, cx_ecfp_private_key_t *key) { - size_t domain_length; - cx_err_t error; - - CX_CHECK(cx_ecdomain_parameters_length(curve, &domain_length)); - - if (!(((raw_key == NULL) && (key_len == 0)) || ((raw_key) && (key_len == domain_length)))) { - error = CX_INVALID_PARAMETER; - goto end; - } +cx_err_t cx_ecfp_init_private_key_no_throw(cx_curve_t curve, + const uint8_t *raw_key, + size_t key_len, + cx_ecfp_private_key_t *key) +{ + size_t domain_length; + cx_err_t error; + + CX_CHECK(cx_ecdomain_parameters_length(curve, &domain_length)); + + if (!(((raw_key == NULL) && (key_len == 0)) || ((raw_key) && (key_len == domain_length)))) { + error = CX_INVALID_PARAMETER; + goto end; + } - if (raw_key) { - key->d_len = key_len; - memmove(key->d, raw_key, key_len); - } + if (raw_key) { + key->d_len = key_len; + memmove(key->d, raw_key, key_len); + } - key->curve = curve; + key->curve = curve; - end: - return error; +end: + return error; } - /* ----------------------------------------------------------------------- */ /* */ /* ----------------------------------------------------------------------- */ -cx_err_t cx_ecfp_init_public_key_no_throw(cx_curve_t curve, const uint8_t *rawkey, size_t key_len, cx_ecfp_public_key_t *key) { - size_t expected_key_len; - size_t expected_compressed_key_len; - size_t size; - cx_err_t error; - - error = cx_ecdomain_parameters_length(curve, &size); - if (error) { - return error; - } - - // SEC: complex assert param dispatched in code.... - - - memset(key, 0, sizeof(cx_ecfp_public_key_t)); - - if (rawkey) { - if (key_len) { - expected_key_len = 0; - expected_compressed_key_len = 0; - - // check key length vs curve - #ifdef HAVE_ECC_WEIERSTRASS - if (CX_CURVE_RANGE(curve, WEIERSTRASS)) { - expected_key_len = 1 + (size)*2; - } - #endif - - #ifdef HAVE_ECC_TWISTED_EDWARDS - if (CX_CURVE_RANGE(curve, TWISTED_EDWARDS)) { - expected_key_len = 1 + (size)*2; - expected_compressed_key_len = 1 + (size); - } - #endif - - #ifdef HAVE_ECC_MONTGOMERY - if (CX_CURVE_RANGE(curve, MONTGOMERY)) { - expected_compressed_key_len = 1 + (size); - } - #endif - - // check key format - if ((key_len == expected_key_len) && (rawkey[0] == 0x04)) { - goto OK; - } - if ((key_len == expected_compressed_key_len) && (rawkey[0] == 0x02)) { - goto OK; - } - } - return INVALID_PARAMETER; - } else { - key_len = 0; - } +cx_err_t cx_ecfp_init_public_key_no_throw(cx_curve_t curve, + const uint8_t *rawkey, + size_t key_len, + cx_ecfp_public_key_t *key) +{ + size_t expected_key_len; + size_t expected_compressed_key_len; + size_t size; + cx_err_t error; + + error = cx_ecdomain_parameters_length(curve, &size); + if (error) { + return error; + } + + // SEC: complex assert param dispatched in code.... + + memset(key, 0, sizeof(cx_ecfp_public_key_t)); + + if (rawkey) { + if (key_len) { + expected_key_len = 0; + expected_compressed_key_len = 0; + +// check key length vs curve +#ifdef HAVE_ECC_WEIERSTRASS + if (CX_CURVE_RANGE(curve, WEIERSTRASS)) { + expected_key_len = 1 + (size) *2; + } +#endif + +#ifdef HAVE_ECC_TWISTED_EDWARDS + if (CX_CURVE_RANGE(curve, TWISTED_EDWARDS)) { + expected_key_len = 1 + (size) *2; + expected_compressed_key_len = 1 + (size); + } +#endif + +#ifdef HAVE_ECC_MONTGOMERY + if (CX_CURVE_RANGE(curve, MONTGOMERY)) { + expected_compressed_key_len = 1 + (size); + } +#endif + + // check key format + if ((key_len == expected_key_len) && (rawkey[0] == 0x04)) { + goto OK; + } + if ((key_len == expected_compressed_key_len) && (rawkey[0] == 0x02)) { + goto OK; + } + } + return INVALID_PARAMETER; + } + else { + key_len = 0; + } OK: - // init key - key->curve = curve; - key->W_len = key_len; - memmove(key->W, rawkey, key_len); + // init key + key->curve = curve; + key->W_len = key_len; + memmove(key->W, rawkey, key_len); - return CX_OK; + return CX_OK; } /* ----------------------------------------------------------------------- */ /* */ /* ----------------------------------------------------------------------- */ cx_err_t cx_ecfp_generate_pair_no_throw(cx_curve_t curve, - cx_ecfp_public_key_t * public_key, - cx_ecfp_private_key_t *private_key, - bool keep_private) { - return cx_ecfp_generate_pair2_no_throw(curve, public_key, private_key, keep_private, CX_SHA512); + cx_ecfp_public_key_t *public_key, + cx_ecfp_private_key_t *private_key, + bool keep_private) +{ + return cx_ecfp_generate_pair2_no_throw(curve, public_key, private_key, keep_private, CX_SHA512); } cx_err_t cx_ecfp_generate_pair2_no_throw(cx_curve_t curve, - cx_ecfp_public_key_t * public_key, - cx_ecfp_private_key_t *private_key, - bool keep_private, - cx_md_t hashID) { - // domain used - size_t size; - cx_bn_t r, a, n; - cx_ecpoint_t W; - cx_err_t error; + cx_ecfp_public_key_t *public_key, + cx_ecfp_private_key_t *private_key, + bool keep_private, + cx_md_t hashID) +{ + // domain used + size_t size; + cx_bn_t r, a, n; + cx_ecpoint_t W; + cx_err_t error; #ifndef HAVE_ECC_TWISTED_EDWARDS - (void) hashID; + (void) hashID; #endif - CX_CHECK(cx_ecdomain_parameters_length(curve, &size)); + CX_CHECK(cx_ecdomain_parameters_length(curve, &size)); - // SEC: complex assert param dispatched in code.... + // SEC: complex assert param dispatched in code.... - CX_CHECK(cx_bn_lock(size, 0)); - CX_CHECK(cx_bn_alloc(&n, size)); - CX_CHECK(cx_ecdomain_parameter_bn(curve, CX_CURVE_PARAM_Order, n)); - CX_CHECK(cx_bn_alloc(&r, size)); + CX_CHECK(cx_bn_lock(size, 0)); + CX_CHECK(cx_bn_alloc(&n, size)); + CX_CHECK(cx_ecdomain_parameter_bn(curve, CX_CURVE_PARAM_Order, n)); + CX_CHECK(cx_bn_alloc(&r, size)); - // generate private key - if (keep_private) { - // keep => check private key - if ((private_key->curve != curve) || (private_key->d_len != size)) { - error = CX_INVALID_PARAMETER; - goto end; + // generate private key + if (keep_private) { + // keep => check private key + if ((private_key->curve != curve) || (private_key->d_len != size)) { + error = CX_INVALID_PARAMETER; + goto end; + } + CX_CHECK(cx_bn_init(r, private_key->d, private_key->d_len)); } - CX_CHECK(cx_bn_init(r, private_key->d, private_key->d_len)); - } else { - CX_CHECK(cx_bn_alloc(&a, 2 * size)); - CX_CHECK(cx_bn_rand(a)); - CX_CHECK(cx_bn_reduce(r, a, n)); - CX_CHECK(cx_bn_destroy(&a)); - CX_CHECK(cx_bn_export(r, private_key->d, size)); - private_key->curve = curve; - private_key->d_len = size; + else { + CX_CHECK(cx_bn_alloc(&a, 2 * size)); + CX_CHECK(cx_bn_rand(a)); + CX_CHECK(cx_bn_reduce(r, a, n)); + CX_CHECK(cx_bn_destroy(&a)); + CX_CHECK(cx_bn_export(r, private_key->d, size)); + private_key->curve = curve; + private_key->d_len = size; #ifdef HAVE_ECC_MONTGOMERY - if (CX_CURVE_RANGE(curve, MONTGOMERY)) { - if (curve == CX_CURVE_Curve25519) { - private_key->d[size - 1] &= 0xF8; - private_key->d[0] = (private_key->d[0] & 0x7F) | 0x40; - } else /* CX_CURVE_Curve448*/{ - private_key->d[size - 1] &= 0xFC; - private_key->d[0] |= 0x80; + if (CX_CURVE_RANGE(curve, MONTGOMERY)) { + if (curve == CX_CURVE_Curve25519) { + private_key->d[size - 1] &= 0xF8; + private_key->d[0] = (private_key->d[0] & 0x7F) | 0x40; + } + else /* CX_CURVE_Curve448*/ { + private_key->d[size - 1] &= 0xFC; + private_key->d[0] |= 0x80; + } } - } #endif - } + } - // generate public key + // generate public key #ifdef HAVE_ECC_WEIERSTRASS - if (CX_CURVE_RANGE(curve, WEIERSTRASS)) { - CX_CHECK(cx_ecpoint_alloc(&W, private_key->curve)); - CX_CHECK(cx_ecdomain_generator_bn(curve, &W)); - // 'cx_ecpoint_rnd_fixed_scalarmul' doesn't support BLS12-381 so far - // use cx_ecpoint_rnd_scalarmul for now - if (CX_CURVE_BLS12_381_G1 == private_key->curve) { - CX_CHECK(cx_ecpoint_rnd_scalarmul(&W, private_key->d, private_key->d_len)); + if (CX_CURVE_RANGE(curve, WEIERSTRASS)) { + CX_CHECK(cx_ecpoint_alloc(&W, private_key->curve)); + CX_CHECK(cx_ecdomain_generator_bn(curve, &W)); + // 'cx_ecpoint_rnd_fixed_scalarmul' doesn't support BLS12-381 so far + // use cx_ecpoint_rnd_scalarmul for now + if (CX_CURVE_BLS12_381_G1 == private_key->curve) { + CX_CHECK(cx_ecpoint_rnd_scalarmul(&W, private_key->d, private_key->d_len)); + } + else { + CX_CHECK(cx_ecpoint_rnd_fixed_scalarmul(&W, private_key->d, private_key->d_len)); + } + public_key->curve = curve; + public_key->W_len = 1 + 2 * size; + public_key->W[0] = 0x04; + CX_CHECK(cx_ecpoint_export(&W, &public_key->W[1], size, &public_key->W[1 + size], size)); + goto end; } - else { - CX_CHECK(cx_ecpoint_rnd_fixed_scalarmul(&W, private_key->d, private_key->d_len)); - } - public_key->curve = curve; - public_key->W_len = 1 + 2 * size; - public_key->W[0] = 0x04; - CX_CHECK(cx_ecpoint_export(&W, &public_key->W[1], size, &public_key->W[1 + size], size)); - goto end; - } #endif #ifdef HAVE_ECC_TWISTED_EDWARDS - if (CX_CURVE_RANGE(curve, TWISTED_EDWARDS)) { - uint8_t scal[114]; - CX_CHECK(cx_eddsa_get_public_key_internal(private_key, hashID, public_key, NULL, 0, NULL, 0, scal)); - goto end; - } + if (CX_CURVE_RANGE(curve, TWISTED_EDWARDS)) { + uint8_t scal[114]; + CX_CHECK(cx_eddsa_get_public_key_internal( + private_key, hashID, public_key, NULL, 0, NULL, 0, scal)); + goto end; + } #endif #ifdef HAVE_ECC_MONTGOMERY - if (CX_CURVE_RANGE(curve, MONTGOMERY)) { - CX_CHECK(cx_ecpoint_alloc(&W, private_key->curve)); - CX_CHECK(cx_ecdomain_generator_bn(curve, &W)); - CX_CHECK(cx_ecpoint_rnd_scalarmul(&W, private_key->d, private_key->d_len)); - public_key->curve = curve; - public_key->W_len = 1 + 2 * size; - public_key->W[0] = 0x04; - CX_CHECK(cx_ecpoint_export(&W, &public_key->W[1], size, &public_key->W[1 + size], size)); - goto end; - } + if (CX_CURVE_RANGE(curve, MONTGOMERY)) { + CX_CHECK(cx_ecpoint_alloc(&W, private_key->curve)); + CX_CHECK(cx_ecdomain_generator_bn(curve, &W)); + CX_CHECK(cx_ecpoint_rnd_scalarmul(&W, private_key->d, private_key->d_len)); + public_key->curve = curve; + public_key->W_len = 1 + 2 * size; + public_key->W[0] = 0x04; + CX_CHECK(cx_ecpoint_export(&W, &public_key->W[1], size, &public_key->W[1 + size], size)); + goto end; + } #endif - error = CX_EC_INVALID_POINT; + error = CX_EC_INVALID_POINT; - end: - cx_bn_unlock(); - return error; +end: + cx_bn_unlock(); + return error; } +cx_err_t cx_ecfp_add_point_no_throw(cx_curve_t curve, + unsigned char *R, + const unsigned char *P, + const unsigned char *Q) +{ + size_t size; + cx_ecpoint_t ecR, ecP, ecQ; + cx_err_t error; + + CX_CHECK(cx_ecdomain_parameters_length(curve, &size)); + CX_CHECK(cx_bn_lock(size, 0)); + + CX_CHECK(cx_ecpoint_alloc(&ecP, curve)); + CX_CHECK(cx_ecpoint_alloc(&ecQ, curve)); + CX_CHECK(cx_ecpoint_alloc(&ecR, curve)); + CX_CHECK(cx_ecpoint_init(&ecP, P + 1, size, P + 1 + size, size)); + CX_CHECK(cx_ecpoint_init(&ecQ, Q + 1, size, Q + 1 + size, size)); + CX_CHECK(cx_ecpoint_add(&ecR, &ecP, &ecQ)); + R[0] = 0x04; + CX_CHECK(cx_ecpoint_export(&ecR, &R[1], size, &R[1 + size], size)); -cx_err_t cx_ecfp_add_point_no_throw(cx_curve_t curve, unsigned char *R, const unsigned char *P, const unsigned char *Q) { - size_t size; - cx_ecpoint_t ecR, ecP, ecQ; - cx_err_t error; - - CX_CHECK(cx_ecdomain_parameters_length(curve, &size)); - CX_CHECK(cx_bn_lock(size, 0)); - - CX_CHECK(cx_ecpoint_alloc(&ecP, curve)); - CX_CHECK(cx_ecpoint_alloc(&ecQ, curve)); - CX_CHECK(cx_ecpoint_alloc(&ecR, curve)); - CX_CHECK(cx_ecpoint_init(&ecP, P+1, size, P+1+size, size)); - CX_CHECK(cx_ecpoint_init(&ecQ, Q+1, size, Q+1+size, size)); - CX_CHECK(cx_ecpoint_add(&ecR, &ecP,&ecQ)); - R[0] = 0x04; - CX_CHECK(cx_ecpoint_export(&ecR, &R[1], size, &R[1 + size], size)); - - end: - cx_bn_unlock(); - return error; +end: + cx_bn_unlock(); + return error; } /* ----------------------------------------------------------------------- */ /* */ /* ----------------------------------------------------------------------- */ -cx_err_t cx_ecfp_scalar_mult_no_throw(cx_curve_t curve, uint8_t *P, const uint8_t *k, size_t k_len) { - size_t size; - cx_ecpoint_t ecP; - cx_err_t error; - - CX_CHECK(cx_ecdomain_parameters_length(curve, &size)); - CX_CHECK(cx_bn_lock(size, 0)); - - CX_CHECK(cx_ecpoint_alloc(&ecP, curve)); - CX_CHECK(cx_ecpoint_init(&ecP, P+1, size, P+1+size, size)); - CX_CHECK(cx_ecpoint_rnd_scalarmul(&ecP, k, k_len)); - P[0] = 0x04; - CX_CHECK(cx_ecpoint_export(&ecP, &P[1], size, &P[1 + size], size)); - - end: - cx_bn_unlock(); - return error; -} +cx_err_t cx_ecfp_scalar_mult_no_throw(cx_curve_t curve, uint8_t *P, const uint8_t *k, size_t k_len) +{ + size_t size; + cx_ecpoint_t ecP; + cx_err_t error; -#ifdef HAVE_ECC_TWISTED_EDWARDS + CX_CHECK(cx_ecdomain_parameters_length(curve, &size)); + CX_CHECK(cx_bn_lock(size, 0)); -cx_err_t cx_edwards_compress_point_no_throw ( cx_curve_t curve, uint8_t * P, size_t P_len ) { - cx_ecpoint_t P_ec; - cx_err_t error; - uint32_t sign; - size_t size; - - UNUSED(P_len); - CX_CHECK(cx_ecdomain_parameters_length(curve, &size)); - CX_CHECK(cx_bn_lock(size, 0)); - CX_CHECK(cx_ecpoint_alloc(&P_ec, curve)); - CX_CHECK(cx_ecpoint_init(&P_ec, P+1, size, P+1+size, size)); - CX_CHECK(cx_ecpoint_compress(&P_ec, P+1, size, &sign)); - cx_encode_coord(P+1, size, sign); - cx_bn_unlock(); - memmove(P+1+size, P+1, size); - P[0] = 0x02; + CX_CHECK(cx_ecpoint_alloc(&ecP, curve)); + CX_CHECK(cx_ecpoint_init(&ecP, P + 1, size, P + 1 + size, size)); + CX_CHECK(cx_ecpoint_rnd_scalarmul(&ecP, k, k_len)); + P[0] = 0x04; + CX_CHECK(cx_ecpoint_export(&ecP, &P[1], size, &P[1 + size], size)); end: - return error; + cx_bn_unlock(); + return error; } -cx_err_t cx_edwards_decompress_point_no_throw ( cx_curve_t curve, uint8_t * P, size_t P_len ) { - cx_ecpoint_t P_ec; - cx_err_t error; - uint32_t sign; - size_t size; - - UNUSED(P_len); - CX_CHECK(cx_ecdomain_parameters_length(curve, &size)); - CX_CHECK(cx_bn_lock(size, 0)); - sign = cx_decode_coord(P+1, size); - CX_CHECK(cx_ecpoint_alloc(&P_ec, curve)); - memmove(P+1+size,P+1, size); - CX_CHECK(cx_ecpoint_decompress(&P_ec, P+1, size, sign)); - CX_CHECK(cx_ecpoint_export(&P_ec, P+1, size, P+1+size, size)); - cx_bn_unlock(); - P[0] = 0x04; +#ifdef HAVE_ECC_TWISTED_EDWARDS + +cx_err_t cx_edwards_compress_point_no_throw(cx_curve_t curve, uint8_t *P, size_t P_len) +{ + cx_ecpoint_t P_ec; + cx_err_t error; + uint32_t sign; + size_t size; + + UNUSED(P_len); + CX_CHECK(cx_ecdomain_parameters_length(curve, &size)); + CX_CHECK(cx_bn_lock(size, 0)); + CX_CHECK(cx_ecpoint_alloc(&P_ec, curve)); + CX_CHECK(cx_ecpoint_init(&P_ec, P + 1, size, P + 1 + size, size)); + CX_CHECK(cx_ecpoint_compress(&P_ec, P + 1, size, &sign)); + cx_encode_coord(P + 1, size, sign); + cx_bn_unlock(); + memmove(P + 1 + size, P + 1, size); + P[0] = 0x02; end: - return error; + return error; } -#endif // HAVE_ECC_TWISTED_EDWARDS +cx_err_t cx_edwards_decompress_point_no_throw(cx_curve_t curve, uint8_t *P, size_t P_len) +{ + cx_ecpoint_t P_ec; + cx_err_t error; + uint32_t sign; + size_t size; + + UNUSED(P_len); + CX_CHECK(cx_ecdomain_parameters_length(curve, &size)); + CX_CHECK(cx_bn_lock(size, 0)); + sign = cx_decode_coord(P + 1, size); + CX_CHECK(cx_ecpoint_alloc(&P_ec, curve)); + memmove(P + 1 + size, P + 1, size); + CX_CHECK(cx_ecpoint_decompress(&P_ec, P + 1, size, sign)); + CX_CHECK(cx_ecpoint_export(&P_ec, P + 1, size, P + 1 + size, size)); + cx_bn_unlock(); + P[0] = 0x04; -static size_t asn1_get_encoded_length_size(size_t len) { - if (len <0x80) { // .. - return 1; - } - if (len<0x100) { - // 81 .. - return 2; - } - if (len<0x10000) { - //82 .. .. - return 3; - } - return 0; +end: + return error; } -//return the length of an asn1 integer, aka '02' L V -static size_t asn1_get_encoded_integer_size(uint8_t const *val, size_t len) { - size_t l0; +#endif // HAVE_ECC_TWISTED_EDWARDS - while (len && (*val == 0)) { - val++; - len--; - } +static size_t asn1_get_encoded_length_size(size_t len) +{ + if (len < 0x80) { // .. + return 1; + } + if (len < 0x100) { + // 81 .. + return 2; + } + if (len < 0x10000) { + // 82 .. .. + return 3; + } + return 0; +} - if (len == 0) { - len = 1; - } else if (*val&0x80u) { - len++; - } +// return the length of an asn1 integer, aka '02' L V +static size_t asn1_get_encoded_integer_size(uint8_t const *val, size_t len) +{ + size_t l0; + while (len && (*val == 0)) { + val++; + len--; + } - l0 = asn1_get_encoded_length_size(len); - if (l0 == 0) { - return 0; - } - return 1 + l0 + len; -} + if (len == 0) { + len = 1; + } + else if (*val & 0x80u) { + len++; + } -static int asn1_insert_tag(uint8_t **p, const uint8_t *end, unsigned int tag) { - if ((end - *p) < 1) { - return 0; - } - **p = tag; - (*p)++; - return 1; + l0 = asn1_get_encoded_length_size(len); + if (l0 == 0) { + return 0; + } + return 1 + l0 + len; } -static int asn1_insert_len(uint8_t **p, const uint8_t *end, size_t len) { - - if (len <0x80) { +static int asn1_insert_tag(uint8_t **p, const uint8_t *end, unsigned int tag) +{ if ((end - *p) < 1) { - return 0; + return 0; } - (*p)[0] = len & 0xFF; - (*p) += 1; + **p = tag; + (*p)++; return 1; - } - - if (len<0x100) { - if ((end - *p) < 2) { - return 0; - } - (*p)[0] = 0x81u; - (*p)[1] = len & 0xFF; - (*p) += 2; - return 2; - } - - if (len<0x10000) { - if ((end - *p) < 3) { - return 0; - } - (*p)[0] = 0x82u; - (*p)[1] = (len>>8) & 0xFF; - (*p)[2] = len & 0xFF; - (*p) += 3; - return 3; - } - - return 0; } -static int asn1_insert_integer(uint8_t **p, const uint8_t *end, const uint8_t *val, size_t len) { +static int asn1_insert_len(uint8_t **p, const uint8_t *end, size_t len) +{ + if (len < 0x80) { + if ((end - *p) < 1) { + return 0; + } + (*p)[0] = len & 0xFF; + (*p) += 1; + return 1; + } + + if (len < 0x100) { + if ((end - *p) < 2) { + return 0; + } + (*p)[0] = 0x81u; + (*p)[1] = len & 0xFF; + (*p) += 2; + return 2; + } + + if (len < 0x10000) { + if ((end - *p) < 3) { + return 0; + } + (*p)[0] = 0x82u; + (*p)[1] = (len >> 8) & 0xFF; + (*p)[2] = len & 0xFF; + (*p) += 3; + return 3; + } - while (len && (*val == 0)) { - val++; - len--; - } - if (!asn1_insert_tag(p, end, 0x02)) { return 0; - } +} - //special case for 0 - if (len == 0) { - if ((end - *p) < 2) { - return 0; +static int asn1_insert_integer(uint8_t **p, const uint8_t *end, const uint8_t *val, size_t len) +{ + while (len && (*val == 0)) { + val++; + len--; + } + if (!asn1_insert_tag(p, end, 0x02)) { + return 0; } - (*p)[0] = 0x01u; - (*p)[1] = 0x00u; - (*p) += 2; - return 1; - } - //cont with len != 0, so val != 0 - if (!asn1_insert_len(p, end, (*val&0x80) ? len+1: len)) { - return 0; - } + // special case for 0 + if (len == 0) { + if ((end - *p) < 2) { + return 0; + } + (*p)[0] = 0x01u; + (*p)[1] = 0x00u; + (*p) += 2; + return 1; + } - if (*val&0x80) { - if ((end - *p) < 1) { - return 0; + // cont with len != 0, so val != 0 + if (!asn1_insert_len(p, end, (*val & 0x80) ? len + 1 : len)) { + return 0; } - **p = 0; - (*p)++; - } - if ((end - *p) < (int)len) { - return 0; - } - memmove(*p, val, len); - (*p) += len; - return 1; + + if (*val & 0x80) { + if ((end - *p) < 1) { + return 0; + } + **p = 0; + (*p)++; + } + if ((end - *p) < (int) len) { + return 0; + } + memmove(*p, val, len); + (*p) += len; + return 1; } /* ----------------------------------------------------------------------- */ /* */ /* ----------------------------------------------------------------------- */ -size_t cx_ecfp_encode_sig_der(uint8_t* sig, size_t sig_len, - const uint8_t* r, size_t r_len, const uint8_t* s, size_t s_len) { - size_t l0, len; - const uint8_t *sig_end = sig + sig_len; - - len = 0; - - l0 = asn1_get_encoded_integer_size(r, r_len); - if (l0==0) { - return 0; - } - len += l0; - - l0 = asn1_get_encoded_integer_size(s, s_len); - if (l0==0) { - return 0; - } - len += l0; +size_t cx_ecfp_encode_sig_der(uint8_t *sig, + size_t sig_len, + const uint8_t *r, + size_t r_len, + const uint8_t *s, + size_t s_len) +{ + size_t l0, len; + const uint8_t *sig_end = sig + sig_len; + + len = 0; + + l0 = asn1_get_encoded_integer_size(r, r_len); + if (l0 == 0) { + return 0; + } + len += l0; + l0 = asn1_get_encoded_integer_size(s, s_len); + if (l0 == 0) { + return 0; + } + len += l0; - if (!asn1_insert_tag(&sig, sig_end, 0x30) || - !asn1_insert_len(&sig, sig_end, len) || - !asn1_insert_integer(&sig, sig_end, r, r_len) || - !asn1_insert_integer(&sig, sig_end, s, s_len) ) { - return 0; + if (!asn1_insert_tag(&sig, sig_end, 0x30) || !asn1_insert_len(&sig, sig_end, len) + || !asn1_insert_integer(&sig, sig_end, r, r_len) + || !asn1_insert_integer(&sig, sig_end, s, s_len)) { + return 0; } - return sig_len -(sig_end-sig); + return sig_len - (sig_end - sig); } -static int asn1_read_len(const uint8_t **p, const uint8_t *end, size_t *len) { - /* Adapted from secp256k1 */ - int lenleft; - unsigned int b1; - *len = 0; +static int asn1_read_len(const uint8_t **p, const uint8_t *end, size_t *len) +{ + /* Adapted from secp256k1 */ + int lenleft; + unsigned int b1; + *len = 0; - if (*p >= end) - return 0; + if (*p >= end) { + return 0; + } - b1 = *((*p)++); - if (b1 == 0xff) { - /* X.690-0207 8.1.3.5.c the value 0xFF shall not be used. */ - return 0; - } - if ((b1 & 0x80u) == 0) { - /* X.690-0207 8.1.3.4 short form length octets */ - *len = b1; - return 1; - } - if (b1 == 0x80) { - /* Indefinite length is not allowed in DER. */ - return 0; - } - /* X.690-207 8.1.3.5 long form length octets */ - lenleft = b1 & 0x7Fu; - if (lenleft > end - *p) { - return 0; - } - if (**p == 0) { - /* Not the shortest possible length encoding. */ - return 0; - } - if ((size_t)lenleft > sizeof(size_t)) { - /* The resulting length would exceed the range of a size_t, so - * certainly longer than the passed array size. - */ - return 0; - } - while (lenleft > 0) { - if ((*len >> ((sizeof(size_t) - 1) * 8)) != 0) { - return 0; + b1 = *((*p)++); + if (b1 == 0xff) { + /* X.690-0207 8.1.3.5.c the value 0xFF shall not be used. */ + return 0; } - *len = (*len << 8u) | **p; - if (*len + lenleft > (size_t)(end - *p)) { - /* Result exceeds the length of the passed array. */ - return 0; + if ((b1 & 0x80u) == 0) { + /* X.690-0207 8.1.3.4 short form length octets */ + *len = b1; + return 1; } - (*p)++; - lenleft--; - } - if (*len < 128) { - /* Not the shortest possible length encoding. */ - return 0; - } - return 1; + if (b1 == 0x80) { + /* Indefinite length is not allowed in DER. */ + return 0; + } + /* X.690-207 8.1.3.5 long form length octets */ + lenleft = b1 & 0x7Fu; + if (lenleft > end - *p) { + return 0; + } + if (**p == 0) { + /* Not the shortest possible length encoding. */ + return 0; + } + if ((size_t) lenleft > sizeof(size_t)) { + /* The resulting length would exceed the range of a size_t, so + * certainly longer than the passed array size. + */ + return 0; + } + while (lenleft > 0) { + if ((*len >> ((sizeof(size_t) - 1) * 8)) != 0) { + return 0; + } + *len = (*len << 8u) | **p; + if (*len + lenleft > (size_t) (end - *p)) { + /* Result exceeds the length of the passed array. */ + return 0; + } + (*p)++; + lenleft--; + } + if (*len < 128) { + /* Not the shortest possible length encoding. */ + return 0; + } + return 1; } -static int asn1_read_tag(const uint8_t **p, const uint8_t *end, size_t *len, int tag) { - if ((end - *p) < 1) return 0; +static int asn1_read_tag(const uint8_t **p, const uint8_t *end, size_t *len, int tag) +{ + if ((end - *p) < 1) { + return 0; + } - if (**p != tag) return 0; + if (**p != tag) { + return 0; + } - (*p)++; - return asn1_read_len(p, end, len); + (*p)++; + return asn1_read_len(p, end, len); } -static int asn1_parse_integer(const uint8_t **p, const uint8_t *end, const uint8_t **n, size_t *n_len) { - size_t len; - int ret = 0; +static int asn1_parse_integer(const uint8_t **p, + const uint8_t *end, + const uint8_t **n, + size_t *n_len) +{ + size_t len; + int ret = 0; - if (!asn1_read_tag(p, end, &len, 0x02)) /* INTEGER */ - goto end; + if (!asn1_read_tag(p, end, &len, 0x02)) { /* INTEGER */ + goto end; + } - if (len == 0 || len > (size_t)(end - *p)) { - goto end; - } + if (len == 0 || len > (size_t) (end - *p)) { + goto end; + } - if (((*p)[0] & 0x80u) == 0x80u) { - /* Truncated, missing leading 0 (negative number) */ - goto end; - } + if (((*p)[0] & 0x80u) == 0x80u) { + /* Truncated, missing leading 0 (negative number) */ + goto end; + } - if ((*p)[0] == 0 && len >= 2 && ((*p)[1] & 0x80u) == 0) { - /* Zeroes have been prepended to the integer */ - goto end; - } + if ((*p)[0] == 0 && len >= 2 && ((*p)[1] & 0x80u) == 0) { + /* Zeroes have been prepended to the integer */ + goto end; + } - while (len > 0 && **p == 0 && *p != end) { /* Skip leading null bytes */ - (*p)++; - len--; - } + while (len > 0 && **p == 0 && *p != end) { /* Skip leading null bytes */ + (*p)++; + len--; + } - *n = *p; - *n_len = len; + *n = *p; + *n_len = len; - *p += len; - ret = 1; + *p += len; + ret = 1; - end: - return ret; +end: + return ret; } /* ----------------------------------------------------------------------- */ /* */ /* ----------------------------------------------------------------------- */ -int cx_ecfp_decode_sig_der(const uint8_t *input, size_t input_len, - size_t max_size, const uint8_t **r, size_t *r_len, const uint8_t **s, size_t *s_len) { - size_t len; - int ret = 0; - const uint8_t *input_end = input + input_len; - - *s = NULL; - *r = NULL; - *s_len = 0; - *r_len = 0; - - const uint8_t *p = (const uint8_t *)input; - - if (!asn1_read_tag(&p, input_end, &len, 0x30)) /* SEQUENCE */ - goto end; +int cx_ecfp_decode_sig_der(const uint8_t *input, + size_t input_len, + size_t max_size, + const uint8_t **r, + size_t *r_len, + const uint8_t **s, + size_t *s_len) +{ + size_t len; + int ret = 0; + const uint8_t *input_end = input + input_len; + + *s = NULL; + *r = NULL; + *s_len = 0; + *r_len = 0; + + const uint8_t *p = (const uint8_t *) input; + + if (!asn1_read_tag(&p, input_end, &len, 0x30)) { /* SEQUENCE */ + goto end; + } - if (p + len != input_end) goto end; + if (p + len != input_end) { + goto end; + } - if (!asn1_parse_integer(&p, input_end, r, r_len) || - !asn1_parse_integer(&p, input_end, s, s_len)) - goto end; + if (!asn1_parse_integer(&p, input_end, r, r_len) + || !asn1_parse_integer(&p, input_end, s, s_len)) { + goto end; + } - if (p != input_end) /* Check if bytes have been appended to the sequence */ - goto end; + if (p != input_end) { /* Check if bytes have been appended to the sequence */ + goto end; + } - if (*r_len > max_size || *s_len > max_size) { - return 0; - } - ret = 1; - end: - return ret; + if (*r_len > max_size || *s_len > max_size) { + return 0; + } + ret = 1; +end: + return ret; } -#endif // HAVE_ECC +#endif // HAVE_ECC diff --git a/lib_cxng/src/cx_ecfp.h b/lib_cxng/src/cx_ecfp.h index a8d661a4b..46fd5a8b9 100644 --- a/lib_cxng/src/cx_ecfp.h +++ b/lib_cxng/src/cx_ecfp.h @@ -1,20 +1,20 @@ /******************************************************************************* -* Ledger Nano S - Secure firmware -* (c) 2022 Ledger -* -* Licensed under the Apache License, Version 2.0 (the "License"); -* you may not use this file except in compliance with the License. -* You may obtain a copy of the License at -* -* http://www.apache.org/licenses/LICENSE-2.0 -* -* Unless required by applicable law or agreed to in writing, software -* distributed under the License is distributed on an "AS IS" BASIS, -* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -* See the License for the specific language governing permissions and -* limitations under the License. -********************************************************************************/ + * Ledger Nano S - Secure firmware + * (c) 2022 Ledger + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + ********************************************************************************/ #ifdef HAVE_ECC @@ -29,27 +29,26 @@ #if defined(BOLOS_RELEASE) && defined(HAVE_ECC_WITH_NO_RANDOMIZE) #error HAVE_ECC_WITH_NO_RANDOMIZE not allowed for release -#endif // HAVE_ECC_WITH_NO_RANDOMIZE - -#define CX_BITLEN2BYTELEN(l) (((uint32_t)(l) + 7) >> 3) +#endif // HAVE_ECC_WITH_NO_RANDOMIZE +#define CX_BITLEN2BYTELEN(l) (((uint32_t) (l) + 7) >> 3) /* Encoding/Decoding */ -size_t cx_ecfp_encode_sig_der(uint8_t * sig, - size_t sig_len, - const uint8_t *r, - size_t r_len, - const uint8_t *s, - size_t s_len); +size_t cx_ecfp_encode_sig_der(uint8_t *sig, + size_t sig_len, + const uint8_t *r, + size_t r_len, + const uint8_t *s, + size_t s_len); int cx_ecfp_decode_sig_der(const uint8_t *sig, size_t sig_len, size_t max_size, const uint8_t **r, - size_t * r_len, + size_t *r_len, const uint8_t **s, - size_t * s_len); + size_t *s_len); -#endif // CX_ECFP_H +#endif // CX_ECFP_H -#endif // HAVE_ECC +#endif // HAVE_ECC diff --git a/lib_cxng/src/cx_ecschnorr.c b/lib_cxng/src/cx_ecschnorr.c index d98250a1b..9218a9258 100644 --- a/lib_cxng/src/cx_ecschnorr.c +++ b/lib_cxng/src/cx_ecschnorr.c @@ -1,20 +1,20 @@ /******************************************************************************* -* Ledger Nano S - Secure firmware -* (c) 2022 Ledger -* -* Licensed under the Apache License, Version 2.0 (the "License"); -* you may not use this file except in compliance with the License. -* You may obtain a copy of the License at -* -* http://www.apache.org/licenses/LICENSE-2.0 -* -* Unless required by applicable law or agreed to in writing, software -* distributed under the License is distributed on an "AS IS" BASIS, -* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -* See the License for the specific language governing permissions and -* limitations under the License. -********************************************************************************/ + * Ledger Nano S - Secure firmware + * (c) 2022 Ledger + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + ********************************************************************************/ #ifdef HAVE_ECSCHNORR @@ -27,701 +27,711 @@ #include -// const char kr[] = {0xe5, 0xa8, 0xd1, 0xd5, 0x29, 0x97, 0x1c, 0x10, 0xca, 0x2a, 0xf3, 0x78, 0x44, 0x4f, 0xb5, 0x44, -// 0xa2, 0x11, 0x70, 0x78, 0x92, 0xc8, 0x89, 0x8f, 0x91, 0xdc, 0xb1, 0x71, 0x58, 0x4e, 0x3d, 0xb9}; +// const char kr[] = {0xe5, 0xa8, 0xd1, 0xd5, 0x29, 0x97, 0x1c, 0x10, 0xca, 0x2a, 0xf3, 0x78, 0x44, +// 0x4f, 0xb5, 0x44, 0xa2, 0x11, 0x70, 0x78, 0x92, 0xc8, 0x89, 0x8f, 0x91, 0xdc, 0xb1, 0x71, 0x58, +// 0x4e, 0x3d, 0xb9}; /* BIP0340 tags for computing the tagged hashes */ -const uint8_t BIP0340_challenge[] = {'B', 'I', 'P', '0', '3', '4', '0', '/', 'c', 'h', 'a', 'l', 'l', 'e', 'n', 'g', 'e'}; -const uint8_t BIP0340_aux[] = {'B', 'I', 'P', '0', '3', '4', '0', '/', 'a', 'u', 'x'}; -const uint8_t BIP0340_nonce[] = {'B', 'I', 'P', '0', '3', '4', '0', '/', 'n', 'o', 'n', 'c', 'e'}; +const uint8_t BIP0340_challenge[] + = {'B', 'I', 'P', '0', '3', '4', '0', '/', 'c', 'h', 'a', 'l', 'l', 'e', 'n', 'g', 'e'}; +const uint8_t BIP0340_aux[] = {'B', 'I', 'P', '0', '3', '4', '0', '/', 'a', 'u', 'x'}; +const uint8_t BIP0340_nonce[] = {'B', 'I', 'P', '0', '3', '4', '0', '/', 'n', 'o', 'n', 'c', 'e'}; cx_err_t cx_ecschnorr_sign_no_throw(const cx_ecfp_private_key_t *pv_key, - uint32_t mode, - cx_md_t hashID, - const uint8_t * msg, - size_t msg_len, - uint8_t * sig, - size_t * sig_len) { + uint32_t mode, + cx_md_t hashID, + const uint8_t *msg, + size_t msg_len, + uint8_t *sig, + size_t *sig_len) +{ #define CX_MAX_TRIES 100 -#define H G_cx.sha256 - - size_t size; - cx_ecpoint_t Q; - cx_bn_t bn_k, bn_d, bn_r, bn_s, bn_n; - uint8_t R[33]; - uint8_t S[32]; - uint8_t P[32]; - int odd; - uint8_t tries; - cx_err_t error; - int diff; - - CX_CHECK(cx_ecdomain_parameters_length(pv_key->curve, &size)); - - // Only secp256k1 is allowed when using CX_ECSCHNORR_BIP0340 - if (((mode & CX_MASK_EC) == CX_ECSCHNORR_BIP0340) && (pv_key->curve != CX_CURVE_SECP256K1)) { - return CX_EC_INVALID_CURVE; - } - - // WARN: only accept weierstrass 256 bits curve for now - if (hashID != CX_SHA256 || size != 32 || - !CX_CURVE_RANGE(pv_key->curve, WEIERSTRASS) || - pv_key->d_len != size) { - return CX_INVALID_PARAMETER; - } - - // Schnorr BIP0340 signature is not DER encoded and is 64-byte long. - if (((mode & CX_MASK_EC) != CX_ECSCHNORR_BIP0340) && (*sig_len < (6 + 2 * (size + 1)))) { - return CX_INVALID_PARAMETER; - } - - CX_CHECK(cx_bn_lock(size, 0)); - CX_CHECK(cx_bn_alloc(&bn_n, size)); - CX_CHECK(cx_ecdomain_parameter_bn(pv_key->curve, CX_CURVE_PARAM_Order, bn_n)); - CX_CHECK(cx_bn_alloc(&bn_k, size)); - CX_CHECK(cx_bn_alloc(&bn_d, size)); - CX_CHECK(cx_bn_alloc(&bn_r, size)); - CX_CHECK(cx_bn_alloc(&bn_s, size)); - CX_CHECK(cx_ecpoint_alloc(&Q, pv_key->curve)); - - if ((mode & CX_MASK_EC) == CX_ECSCHNORR_BIP0340) { - // Q = [d].G - CX_CHECK(cx_ecdomain_generator_bn(pv_key->curve, &Q)); - CX_CHECK(cx_ecpoint_rnd_fixed_scalarmul(&Q, pv_key->d, size)); - // If Qy is even use d otherwise use n-d - CX_CHECK(cx_bn_init(bn_d, pv_key->d, size)); - CX_CHECK(cx_ecpoint_export(&Q, NULL, 0, P, size)); - odd = P[size - 1] & 1; - if (odd) { - CX_CHECK(cx_bn_sub(bn_d, bn_n, bn_d)); - } - // tag_hash = SHA256("BIP0340/aux") - // SHA256(tag_hash || tag_hash || aux_rnd) - cx_sha256_init_no_throw(&H); - cx_hash_no_throw((cx_hash_t *)&H, CX_LAST, BIP0340_aux, sizeof(BIP0340_aux), R, size); - cx_sha256_init_no_throw(&H); - cx_hash_no_throw((cx_hash_t *)&H, 0, R, size, NULL, 0); - cx_hash_no_throw((cx_hash_t *)&H, 0, R, size, NULL, 0); - cx_hash_no_throw((cx_hash_t *)&H, CX_LAST | CX_NO_REINIT, sig, size, R, size); - // t = d ^ SHA256(tag_hash || tag_hash || aux_rnd) - CX_CHECK(cx_bn_init(bn_k, R, size)); - CX_CHECK(cx_bn_xor(bn_r, bn_d, bn_k)); - CX_CHECK(cx_bn_export(bn_r, sig, size)); - // tag_hash = SHA256("BIP0340/nonce") - // SHA256(tag_hash || tag_hash || t || Qx || msg) - cx_sha256_init_no_throw(&H); - cx_hash_no_throw((cx_hash_t *)&H, CX_LAST, BIP0340_nonce, sizeof(BIP0340_nonce), R, size); - cx_sha256_init_no_throw(&H); - cx_hash_no_throw((cx_hash_t *)&H, 0, R, size, NULL, 0); - cx_hash_no_throw((cx_hash_t *)&H, 0, R, size, NULL, 0); - cx_hash_no_throw((cx_hash_t *)&H, 0, sig, size, NULL, 0); - CX_CHECK(cx_ecpoint_export(&Q, P, size, NULL, 0)); - cx_hash_no_throw((cx_hash_t *)&H, 0, P, size, NULL, 0); - cx_hash_no_throw((cx_hash_t *)&H, CX_LAST | CX_NO_REINIT, msg, size, sig, size); - } - - // generate random - tries = 0; - RETRY: - if (tries == CX_MAX_TRIES) { - goto end; - } - - switch (mode & CX_MASK_RND) { - case CX_RND_PROVIDED: - if (tries) { - goto end; - } - CX_CHECK(cx_bn_init(bn_r, sig, size)); - CX_CHECK(cx_bn_reduce(bn_k, bn_r, bn_n)); - break; - - case CX_RND_TRNG: - CX_CHECK(cx_bn_rng(bn_k, bn_n)); - break; - - default: - error = CX_INVALID_PARAMETER; - goto end; - } - if ((mode & CX_MASK_EC) == CX_ECSCHNORR_BIP0340) { - CX_CHECK(cx_bn_cmp_u32(bn_k, 0, &diff)); - if (diff == 0) { - error = CX_INVALID_PARAMETER; - goto end; - } - } - CX_CHECK(cx_bn_export(bn_k, sig, size)); - - // sign - tries++; - RETRY2: - CX_CHECK(cx_ecdomain_generator_bn(pv_key->curve, &Q)); - CX_CHECK(cx_ecpoint_rnd_fixed_scalarmul(&Q, sig, size)); - - switch (mode & CX_MASK_EC) { - case CX_ECSCHNORR_ISO14888_XY: - case CX_ECSCHNORR_ISO14888_X: - // 1. Generate a random k from [1, ..., order-1] - // 2. Q = G*k - // 3. r = H(Q.x||Q.y||M) - // 4. s = (k+r*pv_key.d)%n - cx_sha256_init_no_throw(&H); - CX_CHECK(cx_ecpoint_export(&Q, sig, size, NULL, 0)); - cx_hash_no_throw((cx_hash_t *)&H, 0, sig, size, NULL, 0); - if ((mode & CX_MASK_EC) == CX_ECSCHNORR_ISO14888_XY) { - CX_CHECK(cx_ecpoint_export(&Q, NULL, 0, sig, size)); - cx_hash_no_throw((cx_hash_t *)&H, 0, sig, size, NULL, 0); - } - cx_hash_no_throw((cx_hash_t *)&H, CX_LAST | CX_NO_REINIT, msg, msg_len, R, sizeof(R)); +#define H G_cx.sha256 - CX_CHECK(cx_bn_init(bn_d, R, 32)); - CX_CHECK(cx_bn_reduce(bn_r, bn_d, bn_n)); - CX_CHECK(cx_bn_cmp_u32(bn_r, 0, &diff)); - if (diff == 0) { - cx_bn_unlock(); - goto RETRY; - } + size_t size; + cx_ecpoint_t Q; + cx_bn_t bn_k, bn_d, bn_r, bn_s, bn_n; + uint8_t R[33]; + uint8_t S[32]; + uint8_t P[32]; + int odd; + uint8_t tries; + cx_err_t error; + int diff; - CX_CHECK(cx_bn_init(bn_d, pv_key->d, pv_key->d_len)); - CX_CHECK(cx_bn_mod_mul(bn_s, bn_d, bn_r, bn_n)); - CX_CHECK(cx_bn_mod_add(bn_s, bn_k, bn_s, bn_n)); - CX_CHECK(cx_bn_set_u32(bn_k, 0)); - CX_CHECK(cx_bn_mod_sub(bn_s, bn_s, bn_k, bn_n)); + CX_CHECK(cx_ecdomain_parameters_length(pv_key->curve, &size)); - CX_CHECK(cx_bn_cmp_u32(bn_s, 0, &diff)); - if (diff == 0) { - goto RETRY; - } - CX_CHECK(cx_bn_export(bn_s, S, 32)); - break; - - case CX_ECSCHNORR_BSI03111: - // 1. Q = G*k - // 2. r = H((msg+xQ), and r%n != 0 - // 3. s = (k-r*pv_key.d)%n - // r = H((msg+xQ), and r%n != 0 - cx_sha256_init_no_throw(&H); - cx_hash_no_throw((cx_hash_t *)&H, 0, msg, msg_len, NULL, 0); - CX_CHECK(cx_ecpoint_export(&Q, sig, size, NULL, 0)); - cx_hash_no_throw((cx_hash_t *)&H, CX_LAST | CX_NO_REINIT, sig, size, R, sizeof(R)); - - CX_CHECK(cx_bn_init(bn_d, R, CX_SHA256_SIZE)); - CX_CHECK(cx_bn_reduce(bn_r, bn_d, bn_n)); - CX_CHECK(cx_bn_cmp_u32(bn_r, 0, &diff)); - if (diff == 0) { - goto RETRY; + // Only secp256k1 is allowed when using CX_ECSCHNORR_BIP0340 + if (((mode & CX_MASK_EC) == CX_ECSCHNORR_BIP0340) && (pv_key->curve != CX_CURVE_SECP256K1)) { + return CX_EC_INVALID_CURVE; } - // s = (k-r*pv_key.d)%n - CX_CHECK(cx_bn_init(bn_d, pv_key->d, pv_key->d_len)); - CX_CHECK(cx_bn_mod_mul(bn_s, bn_d, bn_r, bn_n)); - CX_CHECK(cx_bn_mod_sub(bn_s, bn_k, bn_s, bn_n)); - - CX_CHECK(cx_bn_cmp_u32(bn_s, 0, &diff)); - if (diff == 0) { - goto RETRY; - } - CX_CHECK(cx_bn_export(bn_s, S, 32)); - break; - - case CX_ECSCHNORR_Z: - // https://github.com/Zilliqa/Zilliqa/blob/master/src/libCrypto/Schnorr.cpp#L580 - // https://docs.zilliqa.com/whitepaper.pdf - // 1. Generate a random k from [1, ..., order-1] - // 2. Compute the commitment Q = kG, where G is the base point - // 3. Compute the challenge r = H(Q, kpub, m) [CME: mod n according to pdf/code, Q and kpub compressed "02|03 x" - // according to code) - // 4. If r = 0 mod(order), goto 1 - // 4. Compute s = k - r*kpriv mod(order) - // 5. If s = 0 goto 1. - // 5 Signature on m is (r, s) - - // Q - cx_sha256_init_no_throw(&H); - CX_CHECK(cx_ecpoint_export(&Q, NULL, 0, sig, size)); - odd = sig[size - 1] & 1; - CX_CHECK(cx_ecpoint_export(&Q, sig + 1, size, NULL, 0)); - sig[0] = odd ? 0x03 : 0x02; - cx_hash_no_throw((cx_hash_t *)&H, 0, sig, 1 + size, NULL, 0); // Q - // kpub - CX_CHECK(cx_ecdomain_generator_bn(pv_key->curve, &Q)); - CX_CHECK(cx_ecpoint_rnd_fixed_scalarmul(&Q, pv_key->d, pv_key->d_len)); - CX_CHECK(cx_ecpoint_export(&Q, NULL, 0, sig, size)); - odd = sig[size - 1] & 1; - CX_CHECK(cx_ecpoint_export(&Q, sig + 1, size, NULL, 0)); - sig[0] = odd ? 0x03 : 0x02; - cx_hash_no_throw((cx_hash_t *)&H, 0, sig, 1 + size, NULL, 0); // Q - // m - cx_hash_no_throw((cx_hash_t *)&H, CX_LAST | CX_NO_REINIT, msg, msg_len, R, sizeof(R)); - - // Compute the challenge r = H(Q, kpub, m) - //[CME: mod n according to pdf/code, Q and kpub compressed "02|03 x" according to code) - CX_CHECK(cx_bn_init(bn_d, R, CX_SHA256_SIZE)); - CX_CHECK(cx_bn_reduce(bn_r, bn_d, bn_n)); - CX_CHECK(cx_bn_cmp_u32(bn_r, 0, &diff)); - if (diff == 0) { - goto RETRY; + // WARN: only accept weierstrass 256 bits curve for now + if (hashID != CX_SHA256 || size != 32 || !CX_CURVE_RANGE(pv_key->curve, WEIERSTRASS) + || pv_key->d_len != size) { + return CX_INVALID_PARAMETER; } - CX_CHECK(cx_bn_export(bn_r, R, 32)); - CX_CHECK(cx_bn_init(bn_d, pv_key->d, pv_key->d_len)); - CX_CHECK(cx_bn_mod_mul(bn_s, bn_d, bn_r, bn_n)); - CX_CHECK(cx_bn_mod_sub(bn_s, bn_k, bn_s, bn_n)); - CX_CHECK(cx_bn_cmp_u32(bn_s, 0, &diff)); - if (diff == 0) { - goto RETRY; - } - CX_CHECK(cx_bn_export(bn_s, S, 32)); - break; - - case CX_ECSCHNORR_LIBSECP: - // Inputs: 32-byte message m, 32-byte scalar key x (!=0), 32-byte scalar nonce k (!=0) - // 1. Compute point R = k * G. Reject nonce if R's y coordinate is odd (or negate nonce). - // 2. Compute 32-byte r, the serialization of R's x coordinate. - // 3. Compute scalar h = Hash(r || m). Reject nonce if h == 0 or h >= order. - // 4. Compute scalar s = k - h * x. - // 5. The signature is (r, s). - // Q = G*k - CX_CHECK(cx_ecpoint_export(&Q, NULL, 0, sig, size)); - odd = sig[size - 1] & 1; - if (odd) { - // if y is odd, k <- -k mod n = n-k, and retry - CX_CHECK(cx_bn_mod_sub(bn_k, bn_n, bn_k, bn_n)); - CX_CHECK(cx_bn_export(bn_k, sig, size)); - goto RETRY2; - } - // r = xQ - CX_CHECK(cx_ecpoint_export(&Q, R, size, NULL, 0)); - CX_CHECK(cx_bn_init(bn_d, R, size)); - CX_CHECK(cx_bn_reduce(bn_r, bn_d, bn_n)); - CX_CHECK(cx_bn_cmp_u32(bn_r, 0, &diff)); - if (diff == 0) { - goto RETRY; + // Schnorr BIP0340 signature is not DER encoded and is 64-byte long. + if (((mode & CX_MASK_EC) != CX_ECSCHNORR_BIP0340) && (*sig_len < (6 + 2 * (size + 1)))) { + return CX_INVALID_PARAMETER; } - // h = Hash(r || m). - cx_sha256_init_no_throw(&H); - cx_hash_no_throw((cx_hash_t *)&H, 0, R, size, NULL, 0); - cx_hash_no_throw((cx_hash_t *)&H, CX_LAST | CX_NO_REINIT, msg, msg_len, sig, sizeof(S)); - // Reject nonce if h == 0 or h >= order. - CX_CHECK(cx_bn_init(bn_r, sig, 32)); - CX_CHECK(cx_bn_cmp_u32(bn_r, 0, &diff)); - if (diff == 0) { - goto RETRY; - } - CX_CHECK(cx_bn_cmp(bn_r, bn_n, &diff)); - if (diff >= 0) { - goto RETRY; - } - // s = k - h * x. - CX_CHECK(cx_bn_init(bn_d, pv_key->d, pv_key->d_len)); - CX_CHECK(cx_bn_mod_mul(bn_s, bn_d, bn_r, bn_n)); - CX_CHECK(cx_bn_mod_sub(bn_s, bn_k, bn_s, bn_n)); - CX_CHECK(cx_bn_cmp_u32(bn_s, 0, &diff)); - if (diff == 0) { - goto RETRY; - } - CX_CHECK(cx_bn_export(bn_s, S, 32)); - break; - - /* Schnorr signature with secp256k1 according to BIP0340 - ** https://github.com/bitcoin/bips/blob/master/bip-0340.mediawiki */ - - case CX_ECSCHNORR_BIP0340: - CX_CHECK(cx_ecpoint_export(&Q, NULL, 0, sig, size)); - odd = sig[size - 1] & 1; - if (odd) { - CX_CHECK(cx_bn_sub(bn_k, bn_n, bn_k)); - CX_CHECK(cx_bn_export(bn_k, sig, size)); + + CX_CHECK(cx_bn_lock(size, 0)); + CX_CHECK(cx_bn_alloc(&bn_n, size)); + CX_CHECK(cx_ecdomain_parameter_bn(pv_key->curve, CX_CURVE_PARAM_Order, bn_n)); + CX_CHECK(cx_bn_alloc(&bn_k, size)); + CX_CHECK(cx_bn_alloc(&bn_d, size)); + CX_CHECK(cx_bn_alloc(&bn_r, size)); + CX_CHECK(cx_bn_alloc(&bn_s, size)); + CX_CHECK(cx_ecpoint_alloc(&Q, pv_key->curve)); + + if ((mode & CX_MASK_EC) == CX_ECSCHNORR_BIP0340) { + // Q = [d].G + CX_CHECK(cx_ecdomain_generator_bn(pv_key->curve, &Q)); + CX_CHECK(cx_ecpoint_rnd_fixed_scalarmul(&Q, pv_key->d, size)); + // If Qy is even use d otherwise use n-d + CX_CHECK(cx_bn_init(bn_d, pv_key->d, size)); + CX_CHECK(cx_ecpoint_export(&Q, NULL, 0, P, size)); + odd = P[size - 1] & 1; + if (odd) { + CX_CHECK(cx_bn_sub(bn_d, bn_n, bn_d)); + } + // tag_hash = SHA256("BIP0340/aux") + // SHA256(tag_hash || tag_hash || aux_rnd) + cx_sha256_init_no_throw(&H); + cx_hash_no_throw((cx_hash_t *) &H, CX_LAST, BIP0340_aux, sizeof(BIP0340_aux), R, size); + cx_sha256_init_no_throw(&H); + cx_hash_no_throw((cx_hash_t *) &H, 0, R, size, NULL, 0); + cx_hash_no_throw((cx_hash_t *) &H, 0, R, size, NULL, 0); + cx_hash_no_throw((cx_hash_t *) &H, CX_LAST | CX_NO_REINIT, sig, size, R, size); + // t = d ^ SHA256(tag_hash || tag_hash || aux_rnd) + CX_CHECK(cx_bn_init(bn_k, R, size)); + CX_CHECK(cx_bn_xor(bn_r, bn_d, bn_k)); + CX_CHECK(cx_bn_export(bn_r, sig, size)); + // tag_hash = SHA256("BIP0340/nonce") + // SHA256(tag_hash || tag_hash || t || Qx || msg) + cx_sha256_init_no_throw(&H); + cx_hash_no_throw((cx_hash_t *) &H, CX_LAST, BIP0340_nonce, sizeof(BIP0340_nonce), R, size); + cx_sha256_init_no_throw(&H); + cx_hash_no_throw((cx_hash_t *) &H, 0, R, size, NULL, 0); + cx_hash_no_throw((cx_hash_t *) &H, 0, R, size, NULL, 0); + cx_hash_no_throw((cx_hash_t *) &H, 0, sig, size, NULL, 0); + CX_CHECK(cx_ecpoint_export(&Q, P, size, NULL, 0)); + cx_hash_no_throw((cx_hash_t *) &H, 0, P, size, NULL, 0); + cx_hash_no_throw((cx_hash_t *) &H, CX_LAST | CX_NO_REINIT, msg, size, sig, size); + } + + // generate random + tries = 0; +RETRY: + if (tries == CX_MAX_TRIES) { + goto end; + } + + switch (mode & CX_MASK_RND) { + case CX_RND_PROVIDED: + if (tries) { + goto end; + } + CX_CHECK(cx_bn_init(bn_r, sig, size)); + CX_CHECK(cx_bn_reduce(bn_k, bn_r, bn_n)); + break; + + case CX_RND_TRNG: + CX_CHECK(cx_bn_rng(bn_k, bn_n)); + break; + + default: + error = CX_INVALID_PARAMETER; + goto end; } - // Only take the x-coordinate - CX_CHECK(cx_ecpoint_export(&Q, R, size, NULL, 0)); - - // tag_hash = SHA256("BIP0340_challenge") - // e = SHA256(tag_hash || tag_hash || Rx || Px || msg) - cx_sha256_init_no_throw(&H); - cx_hash_no_throw((cx_hash_t *)&H, CX_LAST, BIP0340_challenge, sizeof(BIP0340_challenge), sig, size); - cx_sha256_init_no_throw(&H); - cx_hash_no_throw((cx_hash_t *)&H, 0, sig, size, NULL, 0); - cx_hash_no_throw((cx_hash_t *)&H, 0, sig, size, NULL, 0); - cx_hash_no_throw((cx_hash_t *)&H, 0, R, size, NULL, 0); - cx_hash_no_throw((cx_hash_t *)&H, 0, P, size, NULL, 0); - cx_hash_no_throw((cx_hash_t *)&H, CX_LAST | CX_NO_REINIT, msg, msg_len, sig, size); - - // e = e % n - CX_CHECK(cx_bn_init(bn_s, sig, size)); - CX_CHECK(cx_bn_reduce(bn_r, bn_s, bn_n)); - - // s = (k + e *d) % n - CX_CHECK(cx_bn_mod_mul(bn_s, bn_d, bn_r, bn_n)); - CX_CHECK(cx_bn_mod_add(bn_s, bn_k, bn_s, bn_n)); - CX_CHECK(cx_bn_set_u32(bn_k, 0)); - CX_CHECK(cx_bn_mod_sub(bn_s, bn_s, bn_k, bn_n)); - - CX_CHECK(cx_bn_export(bn_s, S, size)); - break; - - default: - error = CX_INVALID_PARAMETER; - goto end; - } - - end: - cx_hash_destroy((cx_hash_t*)&H); - cx_bn_unlock(); - if (error == CX_OK) { if ((mode & CX_MASK_EC) == CX_ECSCHNORR_BIP0340) { - *sig_len = 64; - memcpy(sig, R, 32); - memcpy(sig + 32, S, 32); - } else { - // encoding - *sig_len = cx_ecfp_encode_sig_der(sig, *sig_len, R, size, S, size); + CX_CHECK(cx_bn_cmp_u32(bn_k, 0, &diff)); + if (diff == 0) { + error = CX_INVALID_PARAMETER; + goto end; + } } + CX_CHECK(cx_bn_export(bn_k, sig, size)); - } - return error; + // sign + tries++; +RETRY2: + CX_CHECK(cx_ecdomain_generator_bn(pv_key->curve, &Q)); + CX_CHECK(cx_ecpoint_rnd_fixed_scalarmul(&Q, sig, size)); + + switch (mode & CX_MASK_EC) { + case CX_ECSCHNORR_ISO14888_XY: + case CX_ECSCHNORR_ISO14888_X: + // 1. Generate a random k from [1, ..., order-1] + // 2. Q = G*k + // 3. r = H(Q.x||Q.y||M) + // 4. s = (k+r*pv_key.d)%n + cx_sha256_init_no_throw(&H); + CX_CHECK(cx_ecpoint_export(&Q, sig, size, NULL, 0)); + cx_hash_no_throw((cx_hash_t *) &H, 0, sig, size, NULL, 0); + if ((mode & CX_MASK_EC) == CX_ECSCHNORR_ISO14888_XY) { + CX_CHECK(cx_ecpoint_export(&Q, NULL, 0, sig, size)); + cx_hash_no_throw((cx_hash_t *) &H, 0, sig, size, NULL, 0); + } + cx_hash_no_throw((cx_hash_t *) &H, CX_LAST | CX_NO_REINIT, msg, msg_len, R, sizeof(R)); + + CX_CHECK(cx_bn_init(bn_d, R, 32)); + CX_CHECK(cx_bn_reduce(bn_r, bn_d, bn_n)); + CX_CHECK(cx_bn_cmp_u32(bn_r, 0, &diff)); + if (diff == 0) { + cx_bn_unlock(); + goto RETRY; + } + + CX_CHECK(cx_bn_init(bn_d, pv_key->d, pv_key->d_len)); + CX_CHECK(cx_bn_mod_mul(bn_s, bn_d, bn_r, bn_n)); + CX_CHECK(cx_bn_mod_add(bn_s, bn_k, bn_s, bn_n)); + CX_CHECK(cx_bn_set_u32(bn_k, 0)); + CX_CHECK(cx_bn_mod_sub(bn_s, bn_s, bn_k, bn_n)); + + CX_CHECK(cx_bn_cmp_u32(bn_s, 0, &diff)); + if (diff == 0) { + goto RETRY; + } + CX_CHECK(cx_bn_export(bn_s, S, 32)); + break; + + case CX_ECSCHNORR_BSI03111: + // 1. Q = G*k + // 2. r = H((msg+xQ), and r%n != 0 + // 3. s = (k-r*pv_key.d)%n + // r = H((msg+xQ), and r%n != 0 + cx_sha256_init_no_throw(&H); + cx_hash_no_throw((cx_hash_t *) &H, 0, msg, msg_len, NULL, 0); + CX_CHECK(cx_ecpoint_export(&Q, sig, size, NULL, 0)); + cx_hash_no_throw((cx_hash_t *) &H, CX_LAST | CX_NO_REINIT, sig, size, R, sizeof(R)); + + CX_CHECK(cx_bn_init(bn_d, R, CX_SHA256_SIZE)); + CX_CHECK(cx_bn_reduce(bn_r, bn_d, bn_n)); + CX_CHECK(cx_bn_cmp_u32(bn_r, 0, &diff)); + if (diff == 0) { + goto RETRY; + } + + // s = (k-r*pv_key.d)%n + CX_CHECK(cx_bn_init(bn_d, pv_key->d, pv_key->d_len)); + CX_CHECK(cx_bn_mod_mul(bn_s, bn_d, bn_r, bn_n)); + CX_CHECK(cx_bn_mod_sub(bn_s, bn_k, bn_s, bn_n)); + + CX_CHECK(cx_bn_cmp_u32(bn_s, 0, &diff)); + if (diff == 0) { + goto RETRY; + } + CX_CHECK(cx_bn_export(bn_s, S, 32)); + break; + + case CX_ECSCHNORR_Z: + // https://github.com/Zilliqa/Zilliqa/blob/master/src/libCrypto/Schnorr.cpp#L580 + // https://docs.zilliqa.com/whitepaper.pdf + // 1. Generate a random k from [1, ..., order-1] + // 2. Compute the commitment Q = kG, where G is the base point + // 3. Compute the challenge r = H(Q, kpub, m) [CME: mod n according to pdf/code, Q and + // kpub compressed "02|03 x" according to code) + // 4. If r = 0 mod(order), goto 1 + // 4. Compute s = k - r*kpriv mod(order) + // 5. If s = 0 goto 1. + // 5 Signature on m is (r, s) + + // Q + cx_sha256_init_no_throw(&H); + CX_CHECK(cx_ecpoint_export(&Q, NULL, 0, sig, size)); + odd = sig[size - 1] & 1; + CX_CHECK(cx_ecpoint_export(&Q, sig + 1, size, NULL, 0)); + sig[0] = odd ? 0x03 : 0x02; + cx_hash_no_throw((cx_hash_t *) &H, 0, sig, 1 + size, NULL, 0); // Q + // kpub + CX_CHECK(cx_ecdomain_generator_bn(pv_key->curve, &Q)); + CX_CHECK(cx_ecpoint_rnd_fixed_scalarmul(&Q, pv_key->d, pv_key->d_len)); + CX_CHECK(cx_ecpoint_export(&Q, NULL, 0, sig, size)); + odd = sig[size - 1] & 1; + CX_CHECK(cx_ecpoint_export(&Q, sig + 1, size, NULL, 0)); + sig[0] = odd ? 0x03 : 0x02; + cx_hash_no_throw((cx_hash_t *) &H, 0, sig, 1 + size, NULL, 0); // Q + // m + cx_hash_no_throw((cx_hash_t *) &H, CX_LAST | CX_NO_REINIT, msg, msg_len, R, sizeof(R)); + + // Compute the challenge r = H(Q, kpub, m) + //[CME: mod n according to pdf/code, Q and kpub compressed "02|03 x" according to code) + CX_CHECK(cx_bn_init(bn_d, R, CX_SHA256_SIZE)); + CX_CHECK(cx_bn_reduce(bn_r, bn_d, bn_n)); + CX_CHECK(cx_bn_cmp_u32(bn_r, 0, &diff)); + if (diff == 0) { + goto RETRY; + } + CX_CHECK(cx_bn_export(bn_r, R, 32)); + + CX_CHECK(cx_bn_init(bn_d, pv_key->d, pv_key->d_len)); + CX_CHECK(cx_bn_mod_mul(bn_s, bn_d, bn_r, bn_n)); + CX_CHECK(cx_bn_mod_sub(bn_s, bn_k, bn_s, bn_n)); + CX_CHECK(cx_bn_cmp_u32(bn_s, 0, &diff)); + if (diff == 0) { + goto RETRY; + } + CX_CHECK(cx_bn_export(bn_s, S, 32)); + break; + + case CX_ECSCHNORR_LIBSECP: + // Inputs: 32-byte message m, 32-byte scalar key x (!=0), 32-byte scalar nonce k (!=0) + // 1. Compute point R = k * G. Reject nonce if R's y coordinate is odd (or negate + // nonce). + // 2. Compute 32-byte r, the serialization of R's x coordinate. + // 3. Compute scalar h = Hash(r || m). Reject nonce if h == 0 or h >= order. + // 4. Compute scalar s = k - h * x. + // 5. The signature is (r, s). + // Q = G*k + CX_CHECK(cx_ecpoint_export(&Q, NULL, 0, sig, size)); + odd = sig[size - 1] & 1; + if (odd) { + // if y is odd, k <- -k mod n = n-k, and retry + CX_CHECK(cx_bn_mod_sub(bn_k, bn_n, bn_k, bn_n)); + CX_CHECK(cx_bn_export(bn_k, sig, size)); + goto RETRY2; + } + // r = xQ + CX_CHECK(cx_ecpoint_export(&Q, R, size, NULL, 0)); + CX_CHECK(cx_bn_init(bn_d, R, size)); + CX_CHECK(cx_bn_reduce(bn_r, bn_d, bn_n)); + CX_CHECK(cx_bn_cmp_u32(bn_r, 0, &diff)); + if (diff == 0) { + goto RETRY; + } + // h = Hash(r || m). + cx_sha256_init_no_throw(&H); + cx_hash_no_throw((cx_hash_t *) &H, 0, R, size, NULL, 0); + cx_hash_no_throw( + (cx_hash_t *) &H, CX_LAST | CX_NO_REINIT, msg, msg_len, sig, sizeof(S)); + // Reject nonce if h == 0 or h >= order. + CX_CHECK(cx_bn_init(bn_r, sig, 32)); + CX_CHECK(cx_bn_cmp_u32(bn_r, 0, &diff)); + if (diff == 0) { + goto RETRY; + } + CX_CHECK(cx_bn_cmp(bn_r, bn_n, &diff)); + if (diff >= 0) { + goto RETRY; + } + // s = k - h * x. + CX_CHECK(cx_bn_init(bn_d, pv_key->d, pv_key->d_len)); + CX_CHECK(cx_bn_mod_mul(bn_s, bn_d, bn_r, bn_n)); + CX_CHECK(cx_bn_mod_sub(bn_s, bn_k, bn_s, bn_n)); + CX_CHECK(cx_bn_cmp_u32(bn_s, 0, &diff)); + if (diff == 0) { + goto RETRY; + } + CX_CHECK(cx_bn_export(bn_s, S, 32)); + break; + + /* Schnorr signature with secp256k1 according to BIP0340 + ** https://github.com/bitcoin/bips/blob/master/bip-0340.mediawiki */ + + case CX_ECSCHNORR_BIP0340: + CX_CHECK(cx_ecpoint_export(&Q, NULL, 0, sig, size)); + odd = sig[size - 1] & 1; + if (odd) { + CX_CHECK(cx_bn_sub(bn_k, bn_n, bn_k)); + CX_CHECK(cx_bn_export(bn_k, sig, size)); + } + // Only take the x-coordinate + CX_CHECK(cx_ecpoint_export(&Q, R, size, NULL, 0)); + + // tag_hash = SHA256("BIP0340_challenge") + // e = SHA256(tag_hash || tag_hash || Rx || Px || msg) + cx_sha256_init_no_throw(&H); + cx_hash_no_throw( + (cx_hash_t *) &H, CX_LAST, BIP0340_challenge, sizeof(BIP0340_challenge), sig, size); + cx_sha256_init_no_throw(&H); + cx_hash_no_throw((cx_hash_t *) &H, 0, sig, size, NULL, 0); + cx_hash_no_throw((cx_hash_t *) &H, 0, sig, size, NULL, 0); + cx_hash_no_throw((cx_hash_t *) &H, 0, R, size, NULL, 0); + cx_hash_no_throw((cx_hash_t *) &H, 0, P, size, NULL, 0); + cx_hash_no_throw((cx_hash_t *) &H, CX_LAST | CX_NO_REINIT, msg, msg_len, sig, size); + + // e = e % n + CX_CHECK(cx_bn_init(bn_s, sig, size)); + CX_CHECK(cx_bn_reduce(bn_r, bn_s, bn_n)); + + // s = (k + e *d) % n + CX_CHECK(cx_bn_mod_mul(bn_s, bn_d, bn_r, bn_n)); + CX_CHECK(cx_bn_mod_add(bn_s, bn_k, bn_s, bn_n)); + CX_CHECK(cx_bn_set_u32(bn_k, 0)); + CX_CHECK(cx_bn_mod_sub(bn_s, bn_s, bn_k, bn_n)); + + CX_CHECK(cx_bn_export(bn_s, S, size)); + break; + + default: + error = CX_INVALID_PARAMETER; + goto end; + } + +end: + cx_hash_destroy((cx_hash_t *) &H); + cx_bn_unlock(); + if (error == CX_OK) { + if ((mode & CX_MASK_EC) == CX_ECSCHNORR_BIP0340) { + *sig_len = 64; + memcpy(sig, R, 32); + memcpy(sig + 32, S, 32); + } + else { + // encoding + *sig_len = cx_ecfp_encode_sig_der(sig, *sig_len, R, size, S, size); + } + } + return error; } bool cx_ecschnorr_verify(const cx_ecfp_public_key_t *pu_key, uint32_t mode, cx_md_t hashID, - const uint8_t * msg, + const uint8_t *msg, size_t msg_len, - const uint8_t * sig, - size_t sig_len) { - size_t size; - const uint8_t * r, *s; - size_t r_len, s_len; - cx_ecpoint_t R, P, Q; - uint8_t x[33]; - bool odd; - volatile int verified; - cx_err_t error; - int diff; - bool is_on_curve = false; - - cx_bn_t bn_d, bn_r, bn_s, bn_n; - cx_bn_t bn_x, bn_y, bn_p; - - CX_CHECK(cx_ecdomain_parameters_length(pu_key->curve, &size)); - - // ECSCHNORR BIP0340 is only defined for secp256k1 - if (((mode & CX_MASK_EC) == CX_ECSCHNORR_BIP0340) && (pu_key->curve != CX_CURVE_SECP256K1)) { - error = CX_EC_INVALID_CURVE; - verified = false; - goto end; - } - - if (!CX_CURVE_RANGE(pu_key->curve, WEIERSTRASS) || - hashID != CX_SHA256 || size != 32 || - pu_key->W_len != 1 + 2 * size) { - return false; - } - - if ((mode & CX_MASK_EC) != CX_ECSCHNORR_BIP0340) { - if (!cx_ecfp_decode_sig_der(sig, sig_len, size, &r, &r_len, &s, &s_len)) { - return false; - } - } - - CX_CHECK(cx_bn_lock(size, 0)); - verified = false; - - CX_CHECK(cx_bn_alloc(&bn_n, size)); - CX_CHECK(cx_ecdomain_parameter_bn(pu_key->curve, CX_CURVE_PARAM_Order, bn_n)); - if ((mode & CX_MASK_EC) == CX_ECSCHNORR_BIP0340) { - CX_CHECK(cx_bn_alloc_init(&bn_r, size, sig, size)); - CX_CHECK(cx_bn_alloc_init(&bn_s, size, sig + size, size)); - } else { - CX_CHECK(cx_bn_alloc_init(&bn_r, size, r, r_len)); - CX_CHECK(cx_bn_alloc_init(&bn_s, size, s, s_len)); - } - - CX_CHECK(cx_bn_alloc(&bn_d, size)); - - CX_CHECK(cx_bn_cmp_u32(bn_r, 0, &diff)); - if (diff == 0) { - goto end; - } - CX_CHECK(cx_bn_cmp_u32(bn_s, 0, &diff)); - if (diff == 0) { - goto end; - } - - CX_CHECK(cx_ecpoint_alloc(&P, pu_key->curve)); - CX_CHECK(cx_ecpoint_alloc(&Q, pu_key->curve)); - CX_CHECK(cx_ecpoint_alloc(&R, pu_key->curve)); - CX_CHECK(cx_ecdomain_generator_bn(pu_key->curve, &P)); - CX_CHECK(cx_ecpoint_init(&Q, &pu_key->W[1], size, &pu_key->W[1 + size], size)); - - switch (mode & CX_MASK_EC) { - case CX_ECSCHNORR_ISO14888_XY: - case CX_ECSCHNORR_ISO14888_X: - // 1. check... - // 2. Q = [s]G - [r]W - // If Q = 0, output Error and terminate. - //3. v = H(Qx||Qy||M). - //4. Output True if v = r, and False otherwise. - - // 1. - CX_CHECK(cx_bn_cmp_u32(bn_r, 0, &diff)); - if (diff == 0) { - break; - } - CX_CHECK(cx_bn_cmp(bn_n, bn_s, &diff)); - if (diff <= 0) { - break; - } - CX_CHECK(cx_bn_cmp_u32(bn_s, 0, &diff)); - if (diff ==0 ) { - break; - } - CX_CHECK(cx_bn_cmp(bn_n, bn_s, &diff)); - if (diff <= 0) { - break; - } + const uint8_t *sig, + size_t sig_len) +{ + size_t size; + const uint8_t *r, *s; + size_t r_len, s_len; + cx_ecpoint_t R, P, Q; + uint8_t x[33]; + bool odd; + volatile int verified; + cx_err_t error; + int diff; + bool is_on_curve = false; - // 2. - // sG - rW - CX_CHECK(cx_ecpoint_neg(&Q)); - CX_CHECK(cx_ecpoint_double_scalarmul_bn(&R, &P, &Q, bn_s, bn_r)); - // 3. - cx_sha256_init_no_throw(&H); - CX_CHECK(cx_ecpoint_export(&R, x, size, NULL, 0)); - cx_hash_no_throw((cx_hash_t *)&H, 0, x, size, NULL, 0); - if ((mode & CX_MASK_EC) == CX_ECSCHNORR_ISO14888_XY) { - CX_CHECK(cx_ecpoint_export(&R, NULL, 0, x, size)); - cx_hash_no_throw((cx_hash_t *)&H, 0, x, size, NULL, 0); - } - cx_hash_no_throw((cx_hash_t *)&H, CX_LAST | CX_NO_REINIT, msg, msg_len, x, sizeof(x)); - // 4. - CX_CHECK(cx_bn_init(bn_s, x, CX_SHA256_SIZE)); - CX_CHECK(cx_bn_cmp(bn_r, bn_s, &diff)); - if (diff == 0) { - verified = true; - } - break; + cx_bn_t bn_d, bn_r, bn_s, bn_n; + cx_bn_t bn_x, bn_y, bn_p; - case CX_ECSCHNORR_BSI03111: - // 1. Verify that r in {0, . . . , 2**t - 1} and s in {1, 2, . . . , n - 1}. - // If the check fails, output False and terminate. - // 2. Q = [s]G + [r]W - // If Q = 0, output Error and terminate. - // 3. v = H(M||Qx) - // 4. Output True if v = r, and False otherwise. + CX_CHECK(cx_ecdomain_parameters_length(pu_key->curve, &size)); - // 1. - CX_CHECK(cx_bn_cmp_u32(bn_r, 0, &diff)); - if (diff == 0) { - break; - } - CX_CHECK(cx_bn_cmp_u32(bn_s, 0, &diff)); - if (diff == 0) { - break; - } - CX_CHECK(cx_bn_cmp(bn_n, bn_s, &diff)); - if (diff <= 0) { - break; + // ECSCHNORR BIP0340 is only defined for secp256k1 + if (((mode & CX_MASK_EC) == CX_ECSCHNORR_BIP0340) && (pu_key->curve != CX_CURVE_SECP256K1)) { + error = CX_EC_INVALID_CURVE; + verified = false; + goto end; } - // 2. - CX_CHECK(cx_ecpoint_double_scalarmul_bn(&R, &P, &Q, bn_s, bn_r)); - // 3. - cx_sha256_init_no_throw(&H); - cx_hash_no_throw((cx_hash_t *)&H, 0, msg, msg_len, NULL, 0); - CX_CHECK(cx_ecpoint_export(&R, x, size, NULL, 0)); - cx_hash_no_throw((cx_hash_t *)&H, CX_LAST | CX_NO_REINIT, x, size, x, sizeof(x)); - // 4. - CX_CHECK(cx_bn_init(bn_s, x, CX_SHA256_SIZE)); - CX_CHECK(cx_bn_cmp(bn_r, bn_s, &diff)); - if (diff == 0) { - verified = true; - } - break; - - case CX_ECSCHNORR_Z: - // The algorithm to check the signature (r, s) on a message m using a public - // key kpub is as follows - // 1. Check if r,s is in [1, ..., order-1] - // 2. Compute Q = sG + r*kpub - // 3. If Q = O (the neutral point), return 0; - // 4. r' = H(Q, kpub, m) [CME: mod n and Q and kpub compressed "02|03 x" according to pdf/code] - // 5. return r' == r - - // r,s is in [1, ..., order-1] - CX_CHECK(cx_bn_cmp_u32(bn_r, 0, &diff)); - if (diff == 0) { - break; + if (!CX_CURVE_RANGE(pu_key->curve, WEIERSTRASS) || hashID != CX_SHA256 || size != 32 + || pu_key->W_len != 1 + 2 * size) { + return false; } - CX_CHECK(cx_bn_cmp(bn_r, bn_n, &diff)); - if (diff >= 0) { - break; + + if ((mode & CX_MASK_EC) != CX_ECSCHNORR_BIP0340) { + if (!cx_ecfp_decode_sig_der(sig, sig_len, size, &r, &r_len, &s, &s_len)) { + return false; + } } - CX_CHECK(cx_bn_cmp_u32(bn_s, 0, &diff)); - if (diff == 0) { - break; + + CX_CHECK(cx_bn_lock(size, 0)); + verified = false; + + CX_CHECK(cx_bn_alloc(&bn_n, size)); + CX_CHECK(cx_ecdomain_parameter_bn(pu_key->curve, CX_CURVE_PARAM_Order, bn_n)); + if ((mode & CX_MASK_EC) == CX_ECSCHNORR_BIP0340) { + CX_CHECK(cx_bn_alloc_init(&bn_r, size, sig, size)); + CX_CHECK(cx_bn_alloc_init(&bn_s, size, sig + size, size)); } - CX_CHECK(cx_bn_cmp(bn_s, bn_n, &diff)); - if (diff >= 0) { - break; + else { + CX_CHECK(cx_bn_alloc_init(&bn_r, size, r, r_len)); + CX_CHECK(cx_bn_alloc_init(&bn_s, size, s, s_len)); } - // Q = sG + r*kpub - CX_CHECK(cx_ecpoint_double_scalarmul_bn(&R, &P, &Q, bn_s, bn_r)); - // r' = H(Q, kpub, m) - cx_sha256_init_no_throw(&H); - // Q - CX_CHECK(cx_ecpoint_export(&R, NULL, 0, x, size)); - odd = x[size - 1] & 1; - CX_CHECK(cx_ecpoint_export(&R, x + 1, size, NULL, 0)); - x[0] = odd ? 0x03 : 0x02; - cx_hash_no_throw((cx_hash_t *)&H, 0, x, 1 + size, NULL, 0); // Q - // kpub - memmove(x + 1, &pu_key->W[1], size); - x[0] = (pu_key->W[1 + 2 * size - 1] & 1) ? 0x03 : 0x02; - cx_hash_no_throw((cx_hash_t *)&H, 0, x, 1 + size, NULL, 0); // kpub - // m - cx_hash_no_throw((cx_hash_t *)&H, CX_LAST | CX_NO_REINIT, msg, msg_len, x, sizeof(x)); // m - - CX_CHECK(cx_bn_init(bn_d, x, CX_SHA256_SIZE)); - CX_CHECK(cx_bn_reduce(bn_s, bn_d, bn_n)); - CX_CHECK(cx_bn_cmp(bn_r, bn_s, &diff)); - if (diff == 0) { - verified = true; - } - break; - - case CX_ECSCHNORR_LIBSECP: - // Verification: - // Inputs: 32-byte message m, public key point Q, signature: (32-byte r, scalar s) - // 1. Signature is invalid if s >= order. - // 2. Signature is invalid if r >= p. - // 3. Compute scalar h = Hash(r || m). Signature is invalid if h == 0 or h >= order. - // 4. Option 1 (faster for single verification): - // 5. Compute point R = h * Q + s * G. Signature is invalid if R is infinity or R's y coordinate is odd. - // 6. Signature is valid if the serialization of R's x coordinate equals r. - // s < order and r < field. - - //1. 2. + CX_CHECK(cx_bn_alloc(&bn_d, size)); + CX_CHECK(cx_bn_cmp_u32(bn_r, 0, &diff)); if (diff == 0) { - verified = false; - break; - } - CX_CHECK(cx_bn_cmp_u32(bn_s, 0, &diff)); - if (diff == 0) { - verified = false; - break; - } - CX_CHECK(cx_bn_cmp(bn_n, bn_s, &diff)); - if (diff <= 0) { - verified = false; - break; + goto end; } - // h = Hash(r||m), and h!=0, and h= 0) { - break; - } - // R = h*W + s*G, and Ry is NOT odd, and Rx=r - CX_CHECK(cx_bn_init(bn_d, s, s_len)); - CX_CHECK(cx_ecpoint_double_scalarmul_bn(&R, &P, &Q, bn_d, bn_s)); - CX_CHECK(cx_ecpoint_export_bn(&R, &bn_s, &bn_d)); - CX_CHECK(cx_bn_is_odd(bn_d, &odd)); - if (odd) { - break; - } - CX_CHECK(cx_bn_cmp(bn_r, bn_s, &diff)); - if (diff == 0) { - verified = true; - } - break; - - /* Schnorr signature verification with secp256k1 according to BIP0340 - ** https://github.com/bitcoin/bips/blob/master/bip-0340.mediawiki */ - - case CX_ECSCHNORR_BIP0340: - // Q = lift_x(pu_key) - CX_CHECK(cx_bn_alloc(&bn_x, size)); - CX_CHECK(cx_bn_alloc(&bn_y, size)); - CX_CHECK(cx_bn_alloc(&bn_p, size)); - CX_CHECK(cx_ecdomain_parameter_bn(pu_key->curve, CX_CURVE_PARAM_Field, bn_p)); - CX_CHECK(cx_ecpoint_export_bn(&Q, &bn_x, & bn_y)); - // c = x^3 + 7 mod p - CX_CHECK(cx_bn_set_u32(bn_s, 3)); - CX_CHECK(cx_bn_mod_pow_bn(bn_r, bn_x, bn_s, bn_p)); - CX_CHECK(cx_bn_set_u32(bn_s, 7)); - CX_CHECK(cx_bn_mod_add(bn_r, bn_r, bn_s, bn_p)); - // y = c^(p+1)/4 mod p - CX_CHECK(cx_bn_copy(bn_s, bn_p)); - CX_CHECK(cx_bn_set_u32(bn_d, 1)); - CX_CHECK(cx_bn_add(bn_s, bn_s, bn_d)); - CX_CHECK(cx_bn_shr(bn_s, 2)); - CX_CHECK(cx_bn_mod_pow_bn(bn_y, bn_r, bn_s, bn_p)); - - CX_CHECK(cx_bn_is_odd(bn_y, &odd)); - // If y is even, Qy = y otherwise Qy = p - y - if (odd) { - CX_CHECK(cx_bn_sub(bn_y, bn_p, bn_y)); - } - CX_CHECK(cx_ecpoint_init_bn(&Q, bn_x, bn_y)); - CX_CHECK(cx_ecpoint_is_on_curve(&Q, &is_on_curve)); - if (!is_on_curve) { - error = CX_EC_INVALID_POINT; - goto end; - } - // tag_hash = SHA256("BIP0340/challenge") - // e = SHA256(tag_hash || tag_hash || r || pu_key || msg) - cx_sha256_init_no_throw(&H); - cx_hash_no_throw((cx_hash_t *)&H, CX_LAST, BIP0340_challenge, sizeof(BIP0340_challenge), x, size); - cx_sha256_init_no_throw(&H); - cx_hash_no_throw((cx_hash_t *)&H, 0, x, size, NULL, 0); - cx_hash_no_throw((cx_hash_t *)&H, 0, x, size, NULL, 0); - cx_hash_no_throw((cx_hash_t *)&H, 0, sig, size, NULL, 0); - cx_hash_no_throw((cx_hash_t *)&H, 0, &pu_key->W[1], size, NULL, 0); - cx_hash_no_throw((cx_hash_t *)&H, CX_LAST | CX_NO_REINIT, msg, msg_len, x, size); - - // e = e % n - CX_CHECK(cx_bn_init(bn_x, x, size)); - CX_CHECK(cx_bn_reduce(bn_r, bn_x, bn_n)); - // n - e - CX_CHECK(cx_bn_sub(bn_r, bn_n, bn_r)); - // s - CX_CHECK(cx_bn_init(bn_s, sig + size, size)); - // [s].P + [n-e].Q where P is the generator of the curve - // and Q is the point representing the public key. - CX_CHECK(cx_ecpoint_double_scalarmul_bn(&R, &P, &Q, bn_s, bn_r)); - CX_CHECK(cx_ecpoint_export_bn(&R, &bn_x, &bn_y)); - CX_CHECK(cx_bn_is_odd(bn_y, &odd)); - // r - CX_CHECK(cx_bn_init(bn_r, sig, size)); - CX_CHECK(cx_bn_cmp(bn_x, bn_r, &diff)); - - if (odd || (diff != 0)) { - error = CX_INVALID_PARAMETER; - goto end; - } - verified = true; - break; - - default: - error = CX_INVALID_PARAMETER; - goto end; - } - - end: - cx_bn_unlock(); - return error == CX_OK && verified; + goto end; + } + + CX_CHECK(cx_ecpoint_alloc(&P, pu_key->curve)); + CX_CHECK(cx_ecpoint_alloc(&Q, pu_key->curve)); + CX_CHECK(cx_ecpoint_alloc(&R, pu_key->curve)); + CX_CHECK(cx_ecdomain_generator_bn(pu_key->curve, &P)); + CX_CHECK(cx_ecpoint_init(&Q, &pu_key->W[1], size, &pu_key->W[1 + size], size)); + + switch (mode & CX_MASK_EC) { + case CX_ECSCHNORR_ISO14888_XY: + case CX_ECSCHNORR_ISO14888_X: + // 1. check... + // 2. Q = [s]G - [r]W + // If Q = 0, output Error and terminate. + // 3. v = H(Qx||Qy||M). + // 4. Output True if v = r, and False otherwise. + + // 1. + CX_CHECK(cx_bn_cmp_u32(bn_r, 0, &diff)); + if (diff == 0) { + break; + } + CX_CHECK(cx_bn_cmp(bn_n, bn_s, &diff)); + if (diff <= 0) { + break; + } + CX_CHECK(cx_bn_cmp_u32(bn_s, 0, &diff)); + if (diff == 0) { + break; + } + CX_CHECK(cx_bn_cmp(bn_n, bn_s, &diff)); + if (diff <= 0) { + break; + } + + // 2. + // sG - rW + CX_CHECK(cx_ecpoint_neg(&Q)); + CX_CHECK(cx_ecpoint_double_scalarmul_bn(&R, &P, &Q, bn_s, bn_r)); + // 3. + cx_sha256_init_no_throw(&H); + CX_CHECK(cx_ecpoint_export(&R, x, size, NULL, 0)); + cx_hash_no_throw((cx_hash_t *) &H, 0, x, size, NULL, 0); + if ((mode & CX_MASK_EC) == CX_ECSCHNORR_ISO14888_XY) { + CX_CHECK(cx_ecpoint_export(&R, NULL, 0, x, size)); + cx_hash_no_throw((cx_hash_t *) &H, 0, x, size, NULL, 0); + } + cx_hash_no_throw((cx_hash_t *) &H, CX_LAST | CX_NO_REINIT, msg, msg_len, x, sizeof(x)); + // 4. + CX_CHECK(cx_bn_init(bn_s, x, CX_SHA256_SIZE)); + CX_CHECK(cx_bn_cmp(bn_r, bn_s, &diff)); + if (diff == 0) { + verified = true; + } + break; + + case CX_ECSCHNORR_BSI03111: + // 1. Verify that r in {0, . . . , 2**t - 1} and s in {1, 2, . . . , n - 1}. + // If the check fails, output False and terminate. + // 2. Q = [s]G + [r]W + // If Q = 0, output Error and terminate. + // 3. v = H(M||Qx) + // 4. Output True if v = r, and False otherwise. + + // 1. + CX_CHECK(cx_bn_cmp_u32(bn_r, 0, &diff)); + if (diff == 0) { + break; + } + CX_CHECK(cx_bn_cmp_u32(bn_s, 0, &diff)); + if (diff == 0) { + break; + } + CX_CHECK(cx_bn_cmp(bn_n, bn_s, &diff)); + if (diff <= 0) { + break; + } + + // 2. + CX_CHECK(cx_ecpoint_double_scalarmul_bn(&R, &P, &Q, bn_s, bn_r)); + // 3. + cx_sha256_init_no_throw(&H); + cx_hash_no_throw((cx_hash_t *) &H, 0, msg, msg_len, NULL, 0); + CX_CHECK(cx_ecpoint_export(&R, x, size, NULL, 0)); + cx_hash_no_throw((cx_hash_t *) &H, CX_LAST | CX_NO_REINIT, x, size, x, sizeof(x)); + // 4. + CX_CHECK(cx_bn_init(bn_s, x, CX_SHA256_SIZE)); + CX_CHECK(cx_bn_cmp(bn_r, bn_s, &diff)); + if (diff == 0) { + verified = true; + } + break; + + case CX_ECSCHNORR_Z: + // The algorithm to check the signature (r, s) on a message m using a public + // key kpub is as follows + // 1. Check if r,s is in [1, ..., order-1] + // 2. Compute Q = sG + r*kpub + // 3. If Q = O (the neutral point), return 0; + // 4. r' = H(Q, kpub, m) [CME: mod n and Q and kpub compressed "02|03 x" according to + // pdf/code] + // 5. return r' == r + + // r,s is in [1, ..., order-1] + CX_CHECK(cx_bn_cmp_u32(bn_r, 0, &diff)); + if (diff == 0) { + break; + } + CX_CHECK(cx_bn_cmp(bn_r, bn_n, &diff)); + if (diff >= 0) { + break; + } + CX_CHECK(cx_bn_cmp_u32(bn_s, 0, &diff)); + if (diff == 0) { + break; + } + CX_CHECK(cx_bn_cmp(bn_s, bn_n, &diff)); + if (diff >= 0) { + break; + } + + // Q = sG + r*kpub + CX_CHECK(cx_ecpoint_double_scalarmul_bn(&R, &P, &Q, bn_s, bn_r)); + // r' = H(Q, kpub, m) + cx_sha256_init_no_throw(&H); + // Q + CX_CHECK(cx_ecpoint_export(&R, NULL, 0, x, size)); + odd = x[size - 1] & 1; + CX_CHECK(cx_ecpoint_export(&R, x + 1, size, NULL, 0)); + x[0] = odd ? 0x03 : 0x02; + cx_hash_no_throw((cx_hash_t *) &H, 0, x, 1 + size, NULL, 0); // Q + // kpub + memmove(x + 1, &pu_key->W[1], size); + x[0] = (pu_key->W[1 + 2 * size - 1] & 1) ? 0x03 : 0x02; + cx_hash_no_throw((cx_hash_t *) &H, 0, x, 1 + size, NULL, 0); // kpub + // m + cx_hash_no_throw( + (cx_hash_t *) &H, CX_LAST | CX_NO_REINIT, msg, msg_len, x, sizeof(x)); // m + + CX_CHECK(cx_bn_init(bn_d, x, CX_SHA256_SIZE)); + CX_CHECK(cx_bn_reduce(bn_s, bn_d, bn_n)); + CX_CHECK(cx_bn_cmp(bn_r, bn_s, &diff)); + if (diff == 0) { + verified = true; + } + break; + + case CX_ECSCHNORR_LIBSECP: + // Verification: + // Inputs: 32-byte message m, public key point Q, signature: (32-byte r, scalar s) + // 1. Signature is invalid if s >= order. + // 2. Signature is invalid if r >= p. + // 3. Compute scalar h = Hash(r || m). Signature is invalid if h == 0 or h >= order. + // 4. Option 1 (faster for single verification): + // 5. Compute point R = h * Q + s * G. Signature is invalid if R is infinity or R's y + // coordinate is odd. + // 6. Signature is valid if the serialization of R's x coordinate equals r. + // s < order and r < field. + + // 1. 2. + CX_CHECK(cx_bn_cmp_u32(bn_r, 0, &diff)); + if (diff == 0) { + verified = false; + break; + } + CX_CHECK(cx_bn_cmp_u32(bn_s, 0, &diff)); + if (diff == 0) { + verified = false; + break; + } + CX_CHECK(cx_bn_cmp(bn_n, bn_s, &diff)); + if (diff <= 0) { + verified = false; + break; + } + // h = Hash(r||m), and h!=0, and h= 0) { + break; + } + // R = h*W + s*G, and Ry is NOT odd, and Rx=r + CX_CHECK(cx_bn_init(bn_d, s, s_len)); + CX_CHECK(cx_ecpoint_double_scalarmul_bn(&R, &P, &Q, bn_d, bn_s)); + CX_CHECK(cx_ecpoint_export_bn(&R, &bn_s, &bn_d)); + CX_CHECK(cx_bn_is_odd(bn_d, &odd)); + if (odd) { + break; + } + CX_CHECK(cx_bn_cmp(bn_r, bn_s, &diff)); + if (diff == 0) { + verified = true; + } + break; + + /* Schnorr signature verification with secp256k1 according to BIP0340 + ** https://github.com/bitcoin/bips/blob/master/bip-0340.mediawiki */ + + case CX_ECSCHNORR_BIP0340: + // Q = lift_x(pu_key) + CX_CHECK(cx_bn_alloc(&bn_x, size)); + CX_CHECK(cx_bn_alloc(&bn_y, size)); + CX_CHECK(cx_bn_alloc(&bn_p, size)); + CX_CHECK(cx_ecdomain_parameter_bn(pu_key->curve, CX_CURVE_PARAM_Field, bn_p)); + CX_CHECK(cx_ecpoint_export_bn(&Q, &bn_x, &bn_y)); + // c = x^3 + 7 mod p + CX_CHECK(cx_bn_set_u32(bn_s, 3)); + CX_CHECK(cx_bn_mod_pow_bn(bn_r, bn_x, bn_s, bn_p)); + CX_CHECK(cx_bn_set_u32(bn_s, 7)); + CX_CHECK(cx_bn_mod_add(bn_r, bn_r, bn_s, bn_p)); + // y = c^(p+1)/4 mod p + CX_CHECK(cx_bn_copy(bn_s, bn_p)); + CX_CHECK(cx_bn_set_u32(bn_d, 1)); + CX_CHECK(cx_bn_add(bn_s, bn_s, bn_d)); + CX_CHECK(cx_bn_shr(bn_s, 2)); + CX_CHECK(cx_bn_mod_pow_bn(bn_y, bn_r, bn_s, bn_p)); + + CX_CHECK(cx_bn_is_odd(bn_y, &odd)); + // If y is even, Qy = y otherwise Qy = p - y + if (odd) { + CX_CHECK(cx_bn_sub(bn_y, bn_p, bn_y)); + } + CX_CHECK(cx_ecpoint_init_bn(&Q, bn_x, bn_y)); + CX_CHECK(cx_ecpoint_is_on_curve(&Q, &is_on_curve)); + if (!is_on_curve) { + error = CX_EC_INVALID_POINT; + goto end; + } + // tag_hash = SHA256("BIP0340/challenge") + // e = SHA256(tag_hash || tag_hash || r || pu_key || msg) + cx_sha256_init_no_throw(&H); + cx_hash_no_throw( + (cx_hash_t *) &H, CX_LAST, BIP0340_challenge, sizeof(BIP0340_challenge), x, size); + cx_sha256_init_no_throw(&H); + cx_hash_no_throw((cx_hash_t *) &H, 0, x, size, NULL, 0); + cx_hash_no_throw((cx_hash_t *) &H, 0, x, size, NULL, 0); + cx_hash_no_throw((cx_hash_t *) &H, 0, sig, size, NULL, 0); + cx_hash_no_throw((cx_hash_t *) &H, 0, &pu_key->W[1], size, NULL, 0); + cx_hash_no_throw((cx_hash_t *) &H, CX_LAST | CX_NO_REINIT, msg, msg_len, x, size); + + // e = e % n + CX_CHECK(cx_bn_init(bn_x, x, size)); + CX_CHECK(cx_bn_reduce(bn_r, bn_x, bn_n)); + // n - e + CX_CHECK(cx_bn_sub(bn_r, bn_n, bn_r)); + // s + CX_CHECK(cx_bn_init(bn_s, sig + size, size)); + // [s].P + [n-e].Q where P is the generator of the curve + // and Q is the point representing the public key. + CX_CHECK(cx_ecpoint_double_scalarmul_bn(&R, &P, &Q, bn_s, bn_r)); + CX_CHECK(cx_ecpoint_export_bn(&R, &bn_x, &bn_y)); + CX_CHECK(cx_bn_is_odd(bn_y, &odd)); + // r + CX_CHECK(cx_bn_init(bn_r, sig, size)); + CX_CHECK(cx_bn_cmp(bn_x, bn_r, &diff)); + + if (odd || (diff != 0)) { + error = CX_INVALID_PARAMETER; + goto end; + } + verified = true; + break; + + default: + error = CX_INVALID_PARAMETER; + goto end; + } + +end: + cx_bn_unlock(); + return error == CX_OK && verified; } -#endif // HAVE_ECSCHNORR +#endif // HAVE_ECSCHNORR diff --git a/lib_cxng/src/cx_eddsa.c b/lib_cxng/src/cx_eddsa.c index 191f749e9..21baf9a25 100644 --- a/lib_cxng/src/cx_eddsa.c +++ b/lib_cxng/src/cx_eddsa.c @@ -1,20 +1,20 @@ /******************************************************************************* -* Ledger Nano S - Secure firmware -* (c) 2022 Ledger -* -* Licensed under the Apache License, Version 2.0 (the "License"); -* you may not use this file except in compliance with the License. -* You may obtain a copy of the License at -* -* http://www.apache.org/licenses/LICENSE-2.0 -* -* Unless required by applicable law or agreed to in writing, software -* distributed under the License is distributed on an "AS IS" BASIS, -* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -* See the License for the specific language governing permissions and -* limitations under the License. -********************************************************************************/ + * Ledger Nano S - Secure firmware + * (c) 2022 Ledger + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + ********************************************************************************/ #ifdef HAVE_ECC_TWISTED_EDWARDS @@ -27,35 +27,37 @@ #include -static void cx_encode_int(uint8_t *v, int len) { - uint8_t t; - int i, j; - i = 0; - j = len - 1; - len = len / 2; - while (len--) { - t = v[i]; - v[i] = v[j]; - v[j] = t; - i++; - j--; - } +static void cx_encode_int(uint8_t *v, int len) +{ + uint8_t t; + int i, j; + i = 0; + j = len - 1; + len = len / 2; + while (len--) { + t = v[i]; + v[i] = v[j]; + v[j] = t; + i++; + j--; + } } #define cx_decode_int(v, l) cx_encode_int(v, l) - -int cx_decode_coord(uint8_t *coord, int len){ - int sign; - cx_encode_int(coord, len); // little endian - sign = coord[0] & 0x80; // x_0 - coord[0] &= 0x7F; // y-coordinate - return sign; +int cx_decode_coord(uint8_t *coord, int len) +{ + int sign; + cx_encode_int(coord, len); // little endian + sign = coord[0] & 0x80; // x_0 + coord[0] &= 0x7F; // y-coordinate + return sign; } -void cx_encode_coord(uint8_t *coord, int len, int sign){ - coord[0] |= sign? 0x80:0x00; - cx_encode_int(coord, len); +void cx_encode_coord(uint8_t *coord, int len, int sign) +{ + coord[0] |= sign ? 0x80 : 0x00; + cx_encode_int(coord, len); } /* ----------------------------------------------------------------------- */ @@ -63,126 +65,130 @@ void cx_encode_coord(uint8_t *coord, int len, int sign){ /* ----------------------------------------------------------------------- */ cx_err_t cx_eddsa_get_public_key_internal(const cx_ecfp_private_key_t *pv_key, cx_md_t hashID, - cx_ecfp_public_key_t * pu_key, - uint8_t * a, + cx_ecfp_public_key_t *pu_key, + uint8_t *a, size_t a_len, - uint8_t * h, + uint8_t *h, size_t h_len, - uint8_t * scal /*tmp*/) { - size_t size; - cx_err_t error; - - CX_CHECK(cx_ecdomain_parameters_length(pv_key->curve, &size)); - - if (!CX_CURVE_RANGE(pv_key->curve, TWISTED_EDWARDS)) { - return CX_INVALID_PARAMETER; - } - if (!((pv_key->d_len == size) || (pv_key->d_len == (2 * size)))) { - return CX_INVALID_PARAMETER; - } - if (!(((a == NULL) && (a_len == 0)) || ((a_len) && (a_len >= size)))) { - return CX_INVALID_PARAMETER; - } - if (!(((h == NULL) && (h_len == 0)) || ((h_len) && (h_len >= size)))) { - return CX_INVALID_PARAMETER; - } - - switch (hashID) { + uint8_t *scal /*tmp*/) +{ + size_t size; + cx_err_t error; + + CX_CHECK(cx_ecdomain_parameters_length(pv_key->curve, &size)); + + if (!CX_CURVE_RANGE(pv_key->curve, TWISTED_EDWARDS)) { + return CX_INVALID_PARAMETER; + } + if (!((pv_key->d_len == size) || (pv_key->d_len == (2 * size)))) { + return CX_INVALID_PARAMETER; + } + if (!(((a == NULL) && (a_len == 0)) || ((a_len) && (a_len >= size)))) { + return CX_INVALID_PARAMETER; + } + if (!(((h == NULL) && (h_len == 0)) || ((h_len) && (h_len >= size)))) { + return CX_INVALID_PARAMETER; + } + + switch (hashID) { #if defined(HAVE_SHA512) - case CX_SHA512: -#endif // HAVE_SHA512 + case CX_SHA512: +#endif // HAVE_SHA512 #if defined(HAVE_SHA3) - case CX_SHAKE256: - case CX_KECCAK: - case CX_SHA3: -#endif // HAVE_SHA3 + case CX_SHAKE256: + case CX_KECCAK: + case CX_SHA3: +#endif // HAVE_SHA3 #if defined(HAVE_BLAKE2) - case CX_BLAKE2B: - if (cx_hash_init_ex(&G_cx.hash_ctx, hashID, size * 2) != CX_OK) { - return CX_INVALID_PARAMETER; + case CX_BLAKE2B: + if (cx_hash_init_ex(&G_cx.hash_ctx, hashID, size * 2) != CX_OK) { + return CX_INVALID_PARAMETER; + } + break; +#endif // HAVE_BLAKE2 + + default: + return CX_INVALID_PARAMETER; } - break; -#endif // HAVE_BLAKE2 - default: - return CX_INVALID_PARAMETER; - } + if (pv_key->d_len == size) { + /* 1. Hash the 32/57-byte private key using SHA-512/shak256-114, storing the digest in + * a 32/114 bytes large buffer, denoted h. Only the lower [CME: first] 32/57 bytes are + * used for generating the public key. + */ + cx_hash_update(&G_cx.hash_ctx, pv_key->d, pv_key->d_len); + cx_hash_final(&G_cx.hash_ctx, scal); + cx_hash_destroy(&G_cx.hash_ctx); + if (pv_key->curve == CX_CURVE_Ed25519) { + /* 2. Prune the buffer: The lowest 3 bits of the first octet are + * cleared, the highest bit of the last octet is cleared, and the + * second highest bit of the last octet is set. + */ + scal[0] &= 0xF8; + scal[31] = (scal[31] & 0x7F) | 0x40; + } + else /* CX_CURVE_Ed448 */ { + /* 2. Prune the buffer: The two least significant bits of the first + * octet are cleared, all eight bits the last octet are cleared, and + * the highest bit of the second to last octet is set. + */ + scal[0] &= 0xFC; + scal[56] = 0; + scal[55] |= 0x80; + } + } + else { + memmove(scal, pv_key->d, pv_key->d_len); + } - if (pv_key->d_len == size) { - /* 1. Hash the 32/57-byte private key using SHA-512/shak256-114, storing the digest in - * a 32/114 bytes large buffer, denoted h. Only the lower [CME: first] 32/57 bytes are - * used for generating the public key. + /* 3. Interpret the buffer as the little-endian integer, forming a + * secret scalar a. Perform a fixed-base scalar multiplication + * [a]B. */ - cx_hash_update(&G_cx.hash_ctx, pv_key->d, pv_key->d_len); - cx_hash_final(&G_cx.hash_ctx, scal); - cx_hash_destroy(&G_cx.hash_ctx); - if (pv_key->curve == CX_CURVE_Ed25519) { - /* 2. Prune the buffer: The lowest 3 bits of the first octet are - * cleared, the highest bit of the last octet is cleared, and the - * second highest bit of the last octet is set. - */ - scal[0] &= 0xF8; - scal[31] = (scal[31] & 0x7F) | 0x40; - } else /* CX_CURVE_Ed448 */ { - /* 2. Prune the buffer: The two least significant bits of the first - * octet are cleared, all eight bits the last octet are cleared, and - * the highest bit of the second to last octet is set. - */ - scal[0] &= 0xFC; - scal[56] = 0; - scal[55] |= 0x80; + cx_decode_int(scal, size); + if (a) { + memmove(a, scal, size); + } + if (h) { + memmove(h, scal + size, size); } - } else { - memmove(scal, pv_key->d, pv_key->d_len); - } - - /* 3. Interpret the buffer as the little-endian integer, forming a - * secret scalar a. Perform a fixed-base scalar multiplication - * [a]B. - */ - cx_decode_int(scal, size); - if (a) { - memmove(a, scal, size); - } - if (h) { - memmove(h, scal + size, size); - } - if (pu_key) { - cx_ecpoint_t W; - CX_CHECK(cx_ecpoint_alloc(&W, pv_key->curve)); - CX_CHECK(cx_ecdomain_generator_bn(pv_key->curve, &W)); - CX_CHECK(cx_ecpoint_rnd_scalarmul(&W, scal, size)); - pu_key->curve = pv_key->curve; - pu_key->W_len = 1 + 2 * size; - pu_key->W[0] = 0x04; - CX_CHECK(cx_ecpoint_export(&W, pu_key->W + 1, size, pu_key->W + 1 + size, size)); - CX_CHECK(cx_ecpoint_destroy(&W)); - } - - end: - return error; + if (pu_key) { + cx_ecpoint_t W; + CX_CHECK(cx_ecpoint_alloc(&W, pv_key->curve)); + CX_CHECK(cx_ecdomain_generator_bn(pv_key->curve, &W)); + CX_CHECK(cx_ecpoint_rnd_scalarmul(&W, scal, size)); + pu_key->curve = pv_key->curve; + pu_key->W_len = 1 + 2 * size; + pu_key->W[0] = 0x04; + CX_CHECK(cx_ecpoint_export(&W, pu_key->W + 1, size, pu_key->W + 1 + size, size)); + CX_CHECK(cx_ecpoint_destroy(&W)); + } + +end: + return error; } cx_err_t cx_eddsa_get_public_key_no_throw(const cx_ecfp_private_key_t *pv_key, - cx_md_t hashID, - cx_ecfp_public_key_t * pu_key, - uint8_t * a, - size_t a_len, - uint8_t * h, - size_t h_len) { - uint8_t scal[114]; - size_t size; - cx_err_t error; - - CX_CHECK(cx_ecdomain_parameters_length(pv_key->curve, &size)); - CX_CHECK(cx_bn_lock(size, 0)); - CX_CHECK(cx_eddsa_get_public_key_internal(pv_key, hashID, pu_key, a, a_len, h, h_len, scal)); - - end: - cx_bn_unlock(); - return error; + cx_md_t hashID, + cx_ecfp_public_key_t *pu_key, + uint8_t *a, + size_t a_len, + uint8_t *h, + size_t h_len) +{ + uint8_t scal[114]; + size_t size; + cx_err_t error; + + CX_CHECK(cx_ecdomain_parameters_length(pv_key->curve, &size)); + CX_CHECK(cx_bn_lock(size, 0)); + CX_CHECK(cx_eddsa_get_public_key_internal(pv_key, hashID, pu_key, a, a_len, h, h_len, scal)); + +end: + cx_bn_unlock(); + return error; } #ifdef HAVE_EDDSA @@ -193,330 +199,334 @@ static uint8_t const C_cx_siged448[] = {'S', 'i', 'g', 'E', 'd', '4', '4', '8'}; /* */ /* ----------------------------------------------------------------------- */ cx_err_t cx_eddsa_sign_no_throw(const cx_ecfp_private_key_t *pv_key, - cx_md_t hashID, - const uint8_t * hash, - size_t hash_len, - uint8_t * sig, - size_t sig_len) { - size_t size, hsize; - cx_bn_t bn_h, bn_a, bn_r, bn_s, bn_n; - cx_ecpoint_t Q; - cx_err_t error; - - uint32_t sign; - uint8_t a[57]; // a - uint8_t r[57]; // r - uint8_t scal[114]; - - CX_CHECK(cx_ecdomain_parameters_length(pv_key->curve, &size)); - - if (!CX_CURVE_RANGE(pv_key->curve, TWISTED_EDWARDS)) { - return CX_INVALID_PARAMETER; - } - if (!((pv_key->d_len == size) || (pv_key->d_len == 2 * size))) { - return CX_INVALID_PARAMETER; - } - if (sig_len < 2 * size) { - return CX_INVALID_PARAMETER; - } - - // check hashID as H function - switch (hashID) { -#if (defined(HAVE_SHA512) || defined(HAVE_SHA3)) -# if defined(HAVE_SHA512) - case CX_SHA512: -# endif // HAVE_SHA512 - -# if defined(HAVE_SHA3) - case CX_KECCAK: - case CX_SHA3: -# endif // HAVE_SHA3 - if (size * 2 != 512 / 8) { - return INVALID_PARAMETER; + cx_md_t hashID, + const uint8_t *hash, + size_t hash_len, + uint8_t *sig, + size_t sig_len) +{ + size_t size, hsize; + cx_bn_t bn_h, bn_a, bn_r, bn_s, bn_n; + cx_ecpoint_t Q; + cx_err_t error; + + uint32_t sign; + uint8_t a[57]; // a + uint8_t r[57]; // r + uint8_t scal[114]; + + CX_CHECK(cx_ecdomain_parameters_length(pv_key->curve, &size)); + + if (!CX_CURVE_RANGE(pv_key->curve, TWISTED_EDWARDS)) { + return CX_INVALID_PARAMETER; + } + if (!((pv_key->d_len == size) || (pv_key->d_len == 2 * size))) { + return CX_INVALID_PARAMETER; + } + if (sig_len < 2 * size) { + return CX_INVALID_PARAMETER; } - break; -#endif // (defined(HAVE_SHA512) || defined(HAVE_SHA3)) + + // check hashID as H function + switch (hashID) { +#if (defined(HAVE_SHA512) || defined(HAVE_SHA3)) +#if defined(HAVE_SHA512) + case CX_SHA512: +#endif // HAVE_SHA512 + +#if defined(HAVE_SHA3) + case CX_KECCAK: + case CX_SHA3: +#endif // HAVE_SHA3 + if (size * 2 != 512 / 8) { + return INVALID_PARAMETER; + } + break; +#endif // (defined(HAVE_SHA512) || defined(HAVE_SHA3)) #if (defined(HAVE_SHA3) || defined(HAVE_BLAKE2)) -# if defined(HAVE_SHA3) - case CX_SHAKE256: -# endif // HAVE_SHA3 - -# if defined(HAVE_BLAKE2) - case CX_BLAKE2B: -# endif // HAVE_BLAKE2 - break; -#endif // (defined(HAVE_SHA3) || defined(HAVE_BLAKE2)) - - default: - return INVALID_PARAMETER; - } - hsize = 2 * size; - - CX_CHECK(cx_bn_lock(size, 0)); - CX_CHECK(cx_ecpoint_alloc(&Q, pv_key->curve)); - CX_CHECK(cx_bn_alloc(&bn_n, size)); - CX_CHECK(cx_ecdomain_parameter_bn(pv_key->curve, CX_CURVE_PARAM_Order, bn_n)); - - // retrieve private scalar a, and private prefix h (stored in r) - CX_CHECK(cx_eddsa_get_public_key_internal(pv_key, hashID, NULL, a, sizeof(a), r, sizeof(r), scal)); - - // compute r - // - last size (32/57) bytes of H(sk), h, as big endian bytes ordered. stored in r - // - r = H(h,M) as little endian - cx_hash_init_ex(&G_cx.hash_ctx, hashID, hsize); - - if (pv_key->curve == CX_CURVE_Ed448) { - cx_hash_update(&G_cx.hash_ctx, C_cx_siged448, sizeof(C_cx_siged448)); - scal[0] = 0; // no ph - scal[1] = 0; // no ctx - cx_hash_update(&G_cx.hash_ctx, scal, 2); - } - cx_hash_update(&G_cx.hash_ctx, r, size); - cx_hash_update(&G_cx.hash_ctx, hash, hash_len); - cx_hash_final(&G_cx.hash_ctx, scal); - cx_hash_destroy(&G_cx.hash_ctx); - cx_encode_int(scal, hsize); - - CX_CHECK(cx_bn_alloc_init(&bn_h, hsize, scal, hsize)); - CX_CHECK(cx_bn_alloc(&bn_r, size)); - CX_CHECK(cx_bn_reduce(bn_r, bn_h, bn_n)); - CX_CHECK(cx_bn_export(bn_r, r, size)); - CX_CHECK(cx_bn_destroy(&bn_h)); - - // compute R = r.B - CX_CHECK(cx_ecdomain_generator_bn(pv_key->curve, &Q)); - // Scalar multiplication with random projective coordinates and additive splitting - CX_CHECK(cx_ecpoint_rnd_scalarmul(&Q, r, size)); - CX_CHECK(cx_ecpoint_compress(&Q, sig, size, &sign)); - cx_encode_coord(sig, size, sign); - - // compute S = r+H(R,A,M).a - // - compute and compress public_key A - CX_CHECK(cx_ecdomain_generator_bn(pv_key->curve, &Q)); - // Scalar multiplication with random projective coordinates and additive splitting - CX_CHECK(cx_ecpoint_rnd_scalarmul(&Q, a, size)); - CX_CHECK(cx_ecpoint_compress(&Q, sig + size, size, &sign)); - cx_encode_coord(sig+size, size, sign); - - // - compute H(R,A,M) - cx_hash_init_ex(&G_cx.hash_ctx, hashID, hsize); - if (pv_key->curve == CX_CURVE_Ed448) { - cx_hash_update(&G_cx.hash_ctx, C_cx_siged448, sizeof(C_cx_siged448)); - scal[0] = 0; // no ph - scal[1] = 0; // no ctx - cx_hash_update(&G_cx.hash_ctx, scal, 2); - } - cx_hash_update(&G_cx.hash_ctx, sig, size); - cx_hash_update(&G_cx.hash_ctx, sig + size, size); - cx_hash_update(&G_cx.hash_ctx, hash, hash_len); - cx_hash_final(&G_cx.hash_ctx, scal); - cx_hash_destroy(&G_cx.hash_ctx); - cx_encode_int(scal, hsize); - - // - compute S = r+H(.)a - - //-- H(R,A,M).a - CX_CHECK(cx_bn_alloc(&bn_s, size)); - CX_CHECK(cx_bn_alloc_init(&bn_h, hsize, scal, hsize)); - CX_CHECK(cx_bn_reduce(bn_r, bn_h, bn_n)); - CX_CHECK(cx_bn_alloc_init(&bn_a, size, a, size)); - CX_CHECK(cx_bn_mod_mul(bn_s, bn_r, bn_a, bn_n)); - //-- r + - CX_CHECK(cx_bn_init(bn_r, r, size)); - CX_CHECK(cx_bn_mod_add(bn_s, bn_s, bn_r, bn_n)); - cx_bn_set_u32(bn_r, 0); - CX_CHECK(cx_bn_mod_sub(bn_s, bn_s, bn_r, bn_n)); - - //- encode - CX_CHECK(cx_bn_export(bn_s, sig + size, size)); - cx_encode_int(sig + size, size); - - end: - cx_bn_unlock(); - return error; +#if defined(HAVE_SHA3) + case CX_SHAKE256: +#endif // HAVE_SHA3 + +#if defined(HAVE_BLAKE2) + case CX_BLAKE2B: +#endif // HAVE_BLAKE2 + break; +#endif // (defined(HAVE_SHA3) || defined(HAVE_BLAKE2)) + + default: + return INVALID_PARAMETER; + } + hsize = 2 * size; + + CX_CHECK(cx_bn_lock(size, 0)); + CX_CHECK(cx_ecpoint_alloc(&Q, pv_key->curve)); + CX_CHECK(cx_bn_alloc(&bn_n, size)); + CX_CHECK(cx_ecdomain_parameter_bn(pv_key->curve, CX_CURVE_PARAM_Order, bn_n)); + + // retrieve private scalar a, and private prefix h (stored in r) + CX_CHECK( + cx_eddsa_get_public_key_internal(pv_key, hashID, NULL, a, sizeof(a), r, sizeof(r), scal)); + + // compute r + // - last size (32/57) bytes of H(sk), h, as big endian bytes ordered. stored in r + // - r = H(h,M) as little endian + cx_hash_init_ex(&G_cx.hash_ctx, hashID, hsize); + + if (pv_key->curve == CX_CURVE_Ed448) { + cx_hash_update(&G_cx.hash_ctx, C_cx_siged448, sizeof(C_cx_siged448)); + scal[0] = 0; // no ph + scal[1] = 0; // no ctx + cx_hash_update(&G_cx.hash_ctx, scal, 2); + } + cx_hash_update(&G_cx.hash_ctx, r, size); + cx_hash_update(&G_cx.hash_ctx, hash, hash_len); + cx_hash_final(&G_cx.hash_ctx, scal); + cx_hash_destroy(&G_cx.hash_ctx); + cx_encode_int(scal, hsize); + + CX_CHECK(cx_bn_alloc_init(&bn_h, hsize, scal, hsize)); + CX_CHECK(cx_bn_alloc(&bn_r, size)); + CX_CHECK(cx_bn_reduce(bn_r, bn_h, bn_n)); + CX_CHECK(cx_bn_export(bn_r, r, size)); + CX_CHECK(cx_bn_destroy(&bn_h)); + + // compute R = r.B + CX_CHECK(cx_ecdomain_generator_bn(pv_key->curve, &Q)); + // Scalar multiplication with random projective coordinates and additive splitting + CX_CHECK(cx_ecpoint_rnd_scalarmul(&Q, r, size)); + CX_CHECK(cx_ecpoint_compress(&Q, sig, size, &sign)); + cx_encode_coord(sig, size, sign); + + // compute S = r+H(R,A,M).a + // - compute and compress public_key A + CX_CHECK(cx_ecdomain_generator_bn(pv_key->curve, &Q)); + // Scalar multiplication with random projective coordinates and additive splitting + CX_CHECK(cx_ecpoint_rnd_scalarmul(&Q, a, size)); + CX_CHECK(cx_ecpoint_compress(&Q, sig + size, size, &sign)); + cx_encode_coord(sig + size, size, sign); + + // - compute H(R,A,M) + cx_hash_init_ex(&G_cx.hash_ctx, hashID, hsize); + if (pv_key->curve == CX_CURVE_Ed448) { + cx_hash_update(&G_cx.hash_ctx, C_cx_siged448, sizeof(C_cx_siged448)); + scal[0] = 0; // no ph + scal[1] = 0; // no ctx + cx_hash_update(&G_cx.hash_ctx, scal, 2); + } + cx_hash_update(&G_cx.hash_ctx, sig, size); + cx_hash_update(&G_cx.hash_ctx, sig + size, size); + cx_hash_update(&G_cx.hash_ctx, hash, hash_len); + cx_hash_final(&G_cx.hash_ctx, scal); + cx_hash_destroy(&G_cx.hash_ctx); + cx_encode_int(scal, hsize); + + // - compute S = r+H(.)a + + //-- H(R,A,M).a + CX_CHECK(cx_bn_alloc(&bn_s, size)); + CX_CHECK(cx_bn_alloc_init(&bn_h, hsize, scal, hsize)); + CX_CHECK(cx_bn_reduce(bn_r, bn_h, bn_n)); + CX_CHECK(cx_bn_alloc_init(&bn_a, size, a, size)); + CX_CHECK(cx_bn_mod_mul(bn_s, bn_r, bn_a, bn_n)); + //-- r + + CX_CHECK(cx_bn_init(bn_r, r, size)); + CX_CHECK(cx_bn_mod_add(bn_s, bn_s, bn_r, bn_n)); + cx_bn_set_u32(bn_r, 0); + CX_CHECK(cx_bn_mod_sub(bn_s, bn_s, bn_r, bn_n)); + + //- encode + CX_CHECK(cx_bn_export(bn_s, sig + size, size)); + cx_encode_int(sig + size, size); + +end: + cx_bn_unlock(); + return error; } /* ----------------------------------------------------------------------- */ /* */ /* ----------------------------------------------------------------------- */ bool cx_eddsa_verify_no_throw(const cx_ecfp_public_key_t *pu_key, - cx_md_t hashID, - const uint8_t * hash, - size_t hash_len, - const uint8_t * sig, - size_t sig_len) { - size_t size, hsize; - uint8_t left[115]; - uint8_t scal[57]; - // Second scalar for double scalar multiplication - uint8_t scal_left[57]; - bool verified, are_equal; - - uint32_t sign; - cx_bn_t bn_h, bn_rs, bn_n; - cx_bn_t bn_p, bn_y; - cx_ecpoint_t Q, R, Right, Left; - cx_err_t error; - int diff; - - CX_CHECK(cx_ecdomain_parameters_length(pu_key->curve, &size)); - - if (!CX_CURVE_RANGE(pu_key->curve, TWISTED_EDWARDS)) { - error = CX_INVALID_PARAMETER; - goto end; - } - if (!((pu_key->W_len == 1 + size) || (pu_key->W_len == 1 + 2 * size))) { - error = CX_INVALID_PARAMETER; - goto end; - } - if (sig_len != 2 * size) { - error = CX_INVALID_PARAMETER; - goto end; - } - - switch (hashID) { -#if (defined(HAVE_SHA512) || defined(HAVE_SHA3)) -# if defined(HAVE_SHA512) - case CX_SHA512: -# endif // HAVE_SHA512 - -# if defined(HAVE_SHA3) - case CX_KECCAK: - case CX_SHA3: -# endif // HAVE_SHA3 - if (size * 2 != 512 / 8) { - error = CX_INVALID_PARAMETER; - goto end; + cx_md_t hashID, + const uint8_t *hash, + size_t hash_len, + const uint8_t *sig, + size_t sig_len) +{ + size_t size, hsize; + uint8_t left[115]; + uint8_t scal[57]; + // Second scalar for double scalar multiplication + uint8_t scal_left[57]; + bool verified, are_equal; + + uint32_t sign; + cx_bn_t bn_h, bn_rs, bn_n; + cx_bn_t bn_p, bn_y; + cx_ecpoint_t Q, R, Right, Left; + cx_err_t error; + int diff; + + CX_CHECK(cx_ecdomain_parameters_length(pu_key->curve, &size)); + + if (!CX_CURVE_RANGE(pu_key->curve, TWISTED_EDWARDS)) { + error = CX_INVALID_PARAMETER; + goto end; + } + if (!((pu_key->W_len == 1 + size) || (pu_key->W_len == 1 + 2 * size))) { + error = CX_INVALID_PARAMETER; + goto end; } - break; -#endif // (defined(HAVE_SHA512) || defined(HAVE_SHA3)) + if (sig_len != 2 * size) { + error = CX_INVALID_PARAMETER; + goto end; + } + + switch (hashID) { +#if (defined(HAVE_SHA512) || defined(HAVE_SHA3)) +#if defined(HAVE_SHA512) + case CX_SHA512: +#endif // HAVE_SHA512 + +#if defined(HAVE_SHA3) + case CX_KECCAK: + case CX_SHA3: +#endif // HAVE_SHA3 + if (size * 2 != 512 / 8) { + error = CX_INVALID_PARAMETER; + goto end; + } + break; +#endif // (defined(HAVE_SHA512) || defined(HAVE_SHA3)) #if (defined(HAVE_SHA3) || defined(HAVE_BLAKE2)) -# if defined(HAVE_SHA3) - case CX_SHAKE256: -# endif // HAVE_SHA3 - -# if defined(HAVE_BLAKE2) - case CX_BLAKE2B: -# endif // HAVE_BLAKE2 - break; -#endif // (defined(HAVE_SHA3) || defined(HAVE_BLAKE2)) - - default: - error = CX_INVALID_PARAMETER; - goto end; - } - - verified = 0; - - hsize = 2 * size; - memset(left, 0, sizeof(left)); - memset(scal, 0, sizeof(scal)); - // set scal_left - memset(scal_left, 0, sizeof(scal_left)); - - CX_CHECK(cx_bn_lock(size, 0)); - CX_CHECK(cx_ecpoint_alloc(&Q, pu_key->curve)); - - // Compute H(R || A || M), - cx_hash_init_ex(&G_cx.hash_ctx, hashID, hsize); - // -prefix for Ed448 - if (pu_key->curve == CX_CURVE_Ed448) { - cx_hash_update(&G_cx.hash_ctx, C_cx_siged448, sizeof(C_cx_siged448)); - scal[0] = 0; // no ph - scal[1] = 0; // no ctx - cx_hash_update(&G_cx.hash_ctx, scal, 2); - } - // -R - cx_hash_update(&G_cx.hash_ctx, sig, size); - // -A, compress public key - if (pu_key->W[0] == 0x04) { +#if defined(HAVE_SHA3) + case CX_SHAKE256: +#endif // HAVE_SHA3 + +#if defined(HAVE_BLAKE2) + case CX_BLAKE2B: +#endif // HAVE_BLAKE2 + break; +#endif // (defined(HAVE_SHA3) || defined(HAVE_BLAKE2)) + + default: + error = CX_INVALID_PARAMETER; + goto end; + } + + verified = 0; + + hsize = 2 * size; + memset(left, 0, sizeof(left)); + memset(scal, 0, sizeof(scal)); + // set scal_left + memset(scal_left, 0, sizeof(scal_left)); + + CX_CHECK(cx_bn_lock(size, 0)); + CX_CHECK(cx_ecpoint_alloc(&Q, pu_key->curve)); + + // Compute H(R || A || M), + cx_hash_init_ex(&G_cx.hash_ctx, hashID, hsize); + // -prefix for Ed448 + if (pu_key->curve == CX_CURVE_Ed448) { + cx_hash_update(&G_cx.hash_ctx, C_cx_siged448, sizeof(C_cx_siged448)); + scal[0] = 0; // no ph + scal[1] = 0; // no ctx + cx_hash_update(&G_cx.hash_ctx, scal, 2); + } + // -R + cx_hash_update(&G_cx.hash_ctx, sig, size); + // -A, compress public key + if (pu_key->W[0] == 0x04) { + CX_CHECK(cx_ecpoint_init(&Q, &pu_key->W[1], size, &pu_key->W[1 + size], size)); + CX_CHECK(cx_ecpoint_compress(&Q, scal, size, &sign)); + cx_encode_coord(scal, size, sign); + } + else { + memmove(scal, &pu_key->W[1], size); + } + cx_hash_update(&G_cx.hash_ctx, scal, size); + // -M + cx_hash_update(&G_cx.hash_ctx, hash, hash_len); + cx_hash_final(&G_cx.hash_ctx, left); + cx_hash_destroy(&G_cx.hash_ctx); + cx_encode_int(left, hsize); + + CX_CHECK(cx_bn_alloc(&bn_n, size)); + CX_CHECK(cx_ecdomain_parameter_bn(pu_key->curve, CX_CURVE_PARAM_Order, bn_n)); + CX_CHECK(cx_bn_alloc(&bn_rs, size)); + + // Use double scalar multiplication and check that R = sB - H(...).A + + // Init the first component of the double scalar: - H(...).A + CX_CHECK(cx_bn_alloc_init(&bn_h, hsize, left, hsize)); + CX_CHECK(cx_bn_reduce(bn_rs, bn_h, bn_n)); + CX_CHECK(cx_bn_export(bn_rs, scal, size)); CX_CHECK(cx_ecpoint_init(&Q, &pu_key->W[1], size, &pu_key->W[1 + size], size)); - CX_CHECK(cx_ecpoint_compress(&Q, scal, size, &sign)); - cx_encode_coord(scal, size, sign); - } else { - memmove(scal, &pu_key->W[1], size); - } - cx_hash_update(&G_cx.hash_ctx, scal, size); - // -M - cx_hash_update(&G_cx.hash_ctx, hash, hash_len); - cx_hash_final(&G_cx.hash_ctx, left); - cx_hash_destroy(&G_cx.hash_ctx); - cx_encode_int(left, hsize); - - CX_CHECK(cx_bn_alloc(&bn_n, size)); - CX_CHECK(cx_ecdomain_parameter_bn(pu_key->curve, CX_CURVE_PARAM_Order, bn_n)); - CX_CHECK(cx_bn_alloc(&bn_rs, size)); - - // Use double scalar multiplication and check that R = sB - H(...).A - - // Init the first component of the double scalar: - H(...).A - CX_CHECK(cx_bn_alloc_init(&bn_h, hsize, left, hsize)); - CX_CHECK(cx_bn_reduce(bn_rs, bn_h, bn_n)); - CX_CHECK(cx_bn_export(bn_rs, scal, size)); - CX_CHECK(cx_ecpoint_init(&Q, &pu_key->W[1], size, &pu_key->W[1 + size], size)); - CX_CHECK(cx_ecpoint_neg(&Q)); - - // Init the second component of the double scalar: s.B - // -> decode s - memmove(scal_left, sig + size, size); - cx_decode_int(scal_left, size); - - // The second half of the signature s must be in range 0 <= s < L to prevent - // signature malleability. - CX_CHECK(cx_bn_alloc_init(&bn_rs, size, scal_left, size)); - CX_CHECK(cx_bn_cmp(bn_rs, bn_n, &diff)); - if (diff >= 0) { - goto end; - } - - CX_CHECK(cx_ecpoint_alloc(&Left, pu_key->curve)); - CX_CHECK(cx_ecdomain_generator_bn(pu_key->curve, &Left)); - - CX_CHECK(cx_ecpoint_alloc(&Right, pu_key->curve)); - - // P = Q - CX_CHECK(cx_ecpoint_cmp(&Left, &Q, &are_equal)); - if (are_equal) { - CX_CHECK(cx_ecpoint_scalarmul(&Left, scal_left, size)); - CX_CHECK(cx_ecpoint_scalarmul(&Q, scal, size)); - CX_CHECK(cx_ecpoint_add(&Right, &Left, &Q)); - } - else{ - // double scalar multiplication sB - H(...)A iff P != +/-Q - CX_CHECK(cx_ecpoint_double_scalarmul(&Right, &Left, &Q, scal_left, size, scal, size)); - } - - // -> decompress R - CX_CHECK(cx_ecpoint_alloc(&R, pu_key->curve)); - memmove(scal, sig, size); - sign = cx_decode_coord(scal, size); - - // field characteristic - CX_CHECK(cx_bn_alloc(&bn_p, size)); - CX_CHECK(cx_ecdomain_parameter_bn(pu_key->curve, CX_CURVE_PARAM_Field, bn_p)); - - // If the y coordinate is >= p then the decoding fails - CX_CHECK(cx_bn_alloc(&bn_y, size)); - CX_CHECK(cx_bn_init(bn_y, scal, size)); - - CX_CHECK(cx_bn_cmp(bn_y, bn_p, &diff)); - if (diff >= 0) { - goto end; - } - - CX_CHECK(cx_ecpoint_decompress(&R, scal, size, sign)); - CX_CHECK(cx_ecpoint_destroy(&Left)); - CX_CHECK(cx_ecpoint_destroy(&Q)); - - // Check the signature - CX_CHECK(cx_ecpoint_cmp(&R, &Right, &verified)); - - end: - cx_bn_unlock(); - return error == CX_OK && verified; + CX_CHECK(cx_ecpoint_neg(&Q)); + + // Init the second component of the double scalar: s.B + // -> decode s + memmove(scal_left, sig + size, size); + cx_decode_int(scal_left, size); + + // The second half of the signature s must be in range 0 <= s < L to prevent + // signature malleability. + CX_CHECK(cx_bn_alloc_init(&bn_rs, size, scal_left, size)); + CX_CHECK(cx_bn_cmp(bn_rs, bn_n, &diff)); + if (diff >= 0) { + goto end; + } + + CX_CHECK(cx_ecpoint_alloc(&Left, pu_key->curve)); + CX_CHECK(cx_ecdomain_generator_bn(pu_key->curve, &Left)); + + CX_CHECK(cx_ecpoint_alloc(&Right, pu_key->curve)); + + // P = Q + CX_CHECK(cx_ecpoint_cmp(&Left, &Q, &are_equal)); + if (are_equal) { + CX_CHECK(cx_ecpoint_scalarmul(&Left, scal_left, size)); + CX_CHECK(cx_ecpoint_scalarmul(&Q, scal, size)); + CX_CHECK(cx_ecpoint_add(&Right, &Left, &Q)); + } + else { + // double scalar multiplication sB - H(...)A iff P != +/-Q + CX_CHECK(cx_ecpoint_double_scalarmul(&Right, &Left, &Q, scal_left, size, scal, size)); + } + + // -> decompress R + CX_CHECK(cx_ecpoint_alloc(&R, pu_key->curve)); + memmove(scal, sig, size); + sign = cx_decode_coord(scal, size); + + // field characteristic + CX_CHECK(cx_bn_alloc(&bn_p, size)); + CX_CHECK(cx_ecdomain_parameter_bn(pu_key->curve, CX_CURVE_PARAM_Field, bn_p)); + + // If the y coordinate is >= p then the decoding fails + CX_CHECK(cx_bn_alloc(&bn_y, size)); + CX_CHECK(cx_bn_init(bn_y, scal, size)); + + CX_CHECK(cx_bn_cmp(bn_y, bn_p, &diff)); + if (diff >= 0) { + goto end; + } + + CX_CHECK(cx_ecpoint_decompress(&R, scal, size, sign)); + CX_CHECK(cx_ecpoint_destroy(&Left)); + CX_CHECK(cx_ecpoint_destroy(&Q)); + + // Check the signature + CX_CHECK(cx_ecpoint_cmp(&R, &Right, &verified)); + +end: + cx_bn_unlock(); + return error == CX_OK && verified; } -#endif // HAVE_EDDSA -#endif // HAVE_ECC_TWISTED_EDWARDS +#endif // HAVE_EDDSA +#endif // HAVE_ECC_TWISTED_EDWARDS diff --git a/lib_cxng/src/cx_eddsa.h b/lib_cxng/src/cx_eddsa.h index f9d831be7..e611f8e7d 100644 --- a/lib_cxng/src/cx_eddsa.h +++ b/lib_cxng/src/cx_eddsa.h @@ -1,20 +1,20 @@ /******************************************************************************* -* Ledger Nano S - Secure firmware -* (c) 2022 Ledger -* -* Licensed under the Apache License, Version 2.0 (the "License"); -* you may not use this file except in compliance with the License. -* You may obtain a copy of the License at -* -* http://www.apache.org/licenses/LICENSE-2.0 -* -* Unless required by applicable law or agreed to in writing, software -* distributed under the License is distributed on an "AS IS" BASIS, -* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -* See the License for the specific language governing permissions and -* limitations under the License. -********************************************************************************/ + * Ledger Nano S - Secure firmware + * (c) 2022 Ledger + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + ********************************************************************************/ #ifdef HAVE_EDDSA @@ -23,12 +23,12 @@ cx_err_t cx_eddsa_get_public_key_internal(const cx_ecfp_private_key_t *pv_key, cx_md_t hashID, - cx_ecfp_public_key_t * pu_key, - uint8_t * a, + cx_ecfp_public_key_t *pu_key, + uint8_t *a, size_t a_len, - uint8_t * h, + uint8_t *h, size_t h_len, - uint8_t * scal /*temp uint8[114]*/); + uint8_t *scal /*temp uint8[114]*/); #endif diff --git a/lib_cxng/src/cx_exported_functions.c b/lib_cxng/src/cx_exported_functions.c index 9bd2ee9c6..ae43ceb8b 100644 --- a/lib_cxng/src/cx_exported_functions.c +++ b/lib_cxng/src/cx_exported_functions.c @@ -23,136 +23,137 @@ #include "cx_sha3.h" #include "cx_blake2b.h" -unsigned long __attribute((section ("._cx_exported_functions"))) cx_exported_functions[] = { - [_NR_cx_aes_dec_block] = (unsigned long)cx_aes_dec_block, - [_NR_cx_aes_enc_block] = (unsigned long)cx_aes_enc_block, - [_NR_cx_aes_gcm_check_tag] = (unsigned long)cx_aes_gcm_check_tag, - [_NR_cx_aes_gcm_decrypt_and_auth] = (unsigned long)cx_aes_gcm_decrypt_and_auth, - [_NR_cx_aes_gcm_encrypt_and_tag] = (unsigned long)cx_aes_gcm_encrypt_and_tag, - [_NR_cx_aes_gcm_finish] = (unsigned long)cx_aes_gcm_finish, - [_NR_cx_aes_gcm_init] = (unsigned long)cx_aes_gcm_init, - [_NR_cx_aes_gcm_set_key] = (unsigned long)cx_aes_gcm_set_key, - [_NR_cx_aes_gcm_start] = (unsigned long)cx_aes_gcm_start, - [_NR_cx_aes_gcm_update_aad] = (unsigned long)cx_aes_gcm_update_aad, - [_NR_cx_aes_gcm_update] = (unsigned long)cx_aes_gcm_update, - [_NR_cx_aes_init_key_no_throw] = (unsigned long)cx_aes_init_key_no_throw, - [_NR_cx_aes_iv_no_throw] = (unsigned long)cx_aes_iv_no_throw, - [_NR_cx_aes_no_throw] = (unsigned long)cx_aes_no_throw, - [_NR_cx_aes_siv_encrypt] = (unsigned long)cx_aes_siv_encrypt, - [_NR_cx_aes_siv_decrypt] = (unsigned long)cx_aes_siv_decrypt, - [_NR_cx_aes_siv_init] = (unsigned long)cx_aes_siv_init, - [_NR_cx_aes_siv_set_key] = (unsigned long)cx_aes_siv_set_key, - [_NR_cx_aes_siv_start] = (unsigned long)cx_aes_siv_start, - [_NR_cx_aes_siv_update_aad] = (unsigned long)cx_aes_siv_update_aad, - [_NR_cx_aes_siv_finish] = (unsigned long)cx_aes_siv_finish, - [_NR_cx_aes_siv_update] = (unsigned long)cx_aes_siv_update, - [_NR_cx_blake2b] = (unsigned long)cx_blake2b, - [_NR_cx_blake2b_final] = (unsigned long)cx_blake2b_final, - [_NR_cx_blake2b_get_output_size] = (unsigned long)cx_blake2b_get_output_size, - [_NR_cx_blake2b_init2_no_throw] = (unsigned long)cx_blake2b_init2_no_throw, - [_NR_cx_blake2b_init_no_throw] = (unsigned long)cx_blake2b_init_no_throw, - [_NR_cx_blake2b_update] = (unsigned long)cx_blake2b_update, - [_NR_cx_cipher_enc_dec] = (unsigned long)cx_cipher_enc_dec, - [_NR_cx_cipher_finish] = (unsigned long)cx_cipher_finish, - [_NR_cx_cipher_init] = (unsigned long)cx_cipher_init, - [_NR_cx_cipher_setiv] = (unsigned long)cx_cipher_setiv, - [_NR_cx_cipher_setkey] = (unsigned long)cx_cipher_setkey, - [_NR_cx_cipher_setup] = (unsigned long)cx_cipher_setup, - [_NR_cx_cipher_set_padding] = (unsigned long)cx_cipher_set_padding, - [_NR_cx_cipher_update] = (unsigned long)cx_cipher_update, - [_NR_cx_cmac] = (unsigned long)cx_cmac, - [_NR_cx_constant_time_eq] = (unsigned long)cx_constant_time_eq, - [_NR_cx_crc16] = (unsigned long)cx_crc16, - [_NR_cx_crc16_update] = (unsigned long)cx_crc16_update, - [_NR_cx_crc32] = (unsigned long)cx_crc32, - [_NR_cx_decode_coord] = (unsigned long)cx_decode_coord, - [_NR_cx_ecdh_no_throw] = (unsigned long)cx_ecdh_no_throw, - [_NR_cx_ecdsa_sign_no_throw] = (unsigned long)cx_ecdsa_sign_no_throw, - [_NR_cx_ecdsa_verify_no_throw] = (unsigned long)cx_ecdsa_verify_no_throw, - [_NR_cx_ecfp_add_point_no_throw] = (unsigned long)cx_ecfp_add_point_no_throw, - [_NR_cx_ecfp_decode_sig_der] = (unsigned long)cx_ecfp_decode_sig_der, - [_NR_cx_ecfp_encode_sig_der] = (unsigned long)cx_ecfp_encode_sig_der, - [_NR_cx_ecfp_generate_pair2_no_throw] = (unsigned long)cx_ecfp_generate_pair2_no_throw, - [_NR_cx_ecfp_generate_pair_no_throw] = (unsigned long)cx_ecfp_generate_pair_no_throw, - [_NR_cx_ecfp_init_private_key_no_throw] = (unsigned long)cx_ecfp_init_private_key_no_throw, - [_NR_cx_ecfp_init_public_key_no_throw] = (unsigned long)cx_ecfp_init_public_key_no_throw, - [_NR_cx_ecfp_scalar_mult_no_throw] = (unsigned long)cx_ecfp_scalar_mult_no_throw, - [_NR_cx_ecschnorr_sign_no_throw] = (unsigned long)cx_ecschnorr_sign_no_throw, - [_NR_cx_ecschnorr_verify] = (unsigned long)cx_ecschnorr_verify, - [_NR_cx_eddsa_get_public_key_internal] = (unsigned long)cx_eddsa_get_public_key_internal, - [_NR_cx_eddsa_get_public_key_no_throw] = (unsigned long)cx_eddsa_get_public_key_no_throw, - [_NR_cx_eddsa_sign_no_throw] = (unsigned long)cx_eddsa_sign_no_throw, - [_NR_cx_eddsa_verify_no_throw] = (unsigned long)cx_eddsa_verify_no_throw, - [_NR_cx_edwards_compress_point_no_throw] = (unsigned long)cx_edwards_compress_point_no_throw, - [_NR_cx_edwards_decompress_point_no_throw] = (unsigned long)cx_edwards_decompress_point_no_throw, - [_NR_cx_encode_coord] = (unsigned long)cx_encode_coord, - [_NR_cx_hash_final] = (unsigned long)cx_hash_final, - [_NR_cx_hash_get_info] = (unsigned long)cx_hash_get_info, - [_NR_cx_hash_get_size] = (unsigned long)cx_hash_get_size, - [_NR_cx_hash_init] = (unsigned long)cx_hash_init, - [_NR_cx_hash_init_ex] = (unsigned long)cx_hash_init_ex, - [_NR_cx_hash_no_throw] = (unsigned long)cx_hash_no_throw, - [_NR_cx_hash_ripemd160] = (unsigned long)cx_hash_ripemd160, - [_NR_cx_hash_sha256] = (unsigned long)cx_hash_sha256, - [_NR_cx_hash_sha512] = (unsigned long)cx_hash_sha512, - [_NR_cx_hash_update] = (unsigned long)cx_hash_update, - [_NR_cx_hkdf_expand] = (unsigned long)cx_hkdf_expand, - [_NR_cx_hkdf_extract] = (unsigned long)cx_hkdf_extract, - [_NR_cx_hmac_final] = (unsigned long)cx_hmac_final, - [_NR_cx_hmac_init] = (unsigned long)cx_hmac_init, - [_NR_cx_hmac_no_throw] = (unsigned long)cx_hmac_no_throw, - [_NR_cx_hmac_ripemd160_init_no_throw] = (unsigned long)cx_hmac_ripemd160_init_no_throw, - [_NR_cx_hmac_sha224_init] = (unsigned long)cx_hmac_sha224_init, - [_NR_cx_hmac_sha256] = (unsigned long)cx_hmac_sha256, - [_NR_cx_hmac_sha256_init_no_throw] = (unsigned long)cx_hmac_sha256_init_no_throw, - [_NR_cx_hmac_sha384_init] = (unsigned long)cx_hmac_sha384_init, - [_NR_cx_hmac_sha512] = (unsigned long)cx_hmac_sha512, - [_NR_cx_hmac_sha512_init_no_throw] = (unsigned long)cx_hmac_sha512_init_no_throw, - [_NR_cx_hmac_update] = (unsigned long)cx_hmac_update, - [_NR_cx_keccak_init_no_throw] = (unsigned long)cx_keccak_init_no_throw, - [_NR_cx_math_addm_no_throw] = (unsigned long)cx_math_addm_no_throw, - [_NR_cx_math_add_no_throw] = (unsigned long)cx_math_add_no_throw, - [_NR_cx_math_cmp_no_throw] = (unsigned long)cx_math_cmp_no_throw, - [_NR_cx_math_invintm_no_throw] = (unsigned long)cx_math_invintm_no_throw, - [_NR_cx_math_invprimem_no_throw] = (unsigned long)cx_math_invprimem_no_throw, - [_NR_cx_math_is_prime_no_throw] = (unsigned long)cx_math_is_prime_no_throw, - [_NR_cx_math_modm_no_throw] = (unsigned long)cx_math_modm_no_throw, - [_NR_cx_math_multm_no_throw] = (unsigned long)cx_math_multm_no_throw, - [_NR_cx_math_mult_no_throw] = (unsigned long)cx_math_mult_no_throw, - [_NR_cx_math_next_prime_no_throw] = (unsigned long)cx_math_next_prime_no_throw, - [_NR_cx_math_powm_no_throw] = (unsigned long)cx_math_powm_no_throw, - [_NR_cx_math_subm_no_throw] = (unsigned long)cx_math_subm_no_throw, - [_NR_cx_math_sub_no_throw] = (unsigned long)cx_math_sub_no_throw, - [_NR_cx_memxor] = (unsigned long)cx_memxor, - [_NR_cx_pbkdf2_hmac] = (unsigned long)cx_pbkdf2_hmac, - [_NR_cx_pbkdf2_no_throw] = (unsigned long)cx_pbkdf2_no_throw, - [_NR_cx_ripemd160_final] = (unsigned long)cx_ripemd160_final, - [_NR_cx_ripemd160_init_no_throw] = (unsigned long)cx_ripemd160_init_no_throw, - [_NR_cx_ripemd160_update] = (unsigned long)cx_ripemd160_update, - [_NR_cx_rng_no_throw] = (unsigned long)cx_rng_no_throw, - [_NR_cx_rng_rfc6979] = (unsigned long)cx_rng_rfc6979, - [_NR_cx_rng_rfc6979_init] = (unsigned long)cx_rng_rfc6979_init, - [_NR_cx_rng_rfc6979_next] = (unsigned long)cx_rng_rfc6979_next, - [_NR_cx_rng_u32_range_func] = (unsigned long)cx_rng_u32_range_func, - [_NR_cx_sha224_init_no_throw] = (unsigned long)cx_sha224_init_no_throw, - [_NR_cx_sha256_final] = (unsigned long)cx_sha256_final, - [_NR_cx_sha256_init_no_throw] = (unsigned long)cx_sha256_init_no_throw, - [_NR_cx_sha256_update] = (unsigned long)cx_sha256_update, - [_NR_cx_sha384_init_no_throw] = (unsigned long)cx_sha384_init_no_throw, - [_NR_cx_sha3_final] = (unsigned long)cx_sha3_final, - [_NR_cx_sha3_get_output_size] = (unsigned long)cx_sha3_get_output_size, - [_NR_cx_sha3_init_no_throw] = (unsigned long)cx_sha3_init_no_throw, - [_NR_cx_sha3_update] = (unsigned long)cx_sha3_update, - [_NR_cx_sha3_xof_init_no_throw] = (unsigned long)cx_sha3_xof_init_no_throw, - [_NR_cx_sha512_final] = (unsigned long)cx_sha512_final, - [_NR_cx_sha512_init_no_throw] = (unsigned long)cx_sha512_init_no_throw, - [_NR_cx_sha512_update] = (unsigned long)cx_sha512_update, - [_NR_cx_shake128_init_no_throw] = (unsigned long)cx_shake128_init_no_throw, - [_NR_cx_shake256_init_no_throw] = (unsigned long)cx_shake256_init_no_throw, - [_NR_cx_swap_buffer32] = (unsigned long)cx_swap_buffer32, - [_NR_cx_swap_buffer64] = (unsigned long)cx_swap_buffer64, - [_NR_cx_swap_uint32] = (unsigned long)cx_swap_uint32, - [_NR_cx_swap_uint64] = (unsigned long)cx_swap_uint64, - [_NR_cx_x25519] = (unsigned long)cx_x25519, - [_NR_cx_x448] = (unsigned long)cx_x448, +unsigned long __attribute((section("._cx_exported_functions"))) cx_exported_functions[] = { + [_NR_cx_aes_dec_block] = (unsigned long) cx_aes_dec_block, + [_NR_cx_aes_enc_block] = (unsigned long) cx_aes_enc_block, + [_NR_cx_aes_gcm_check_tag] = (unsigned long) cx_aes_gcm_check_tag, + [_NR_cx_aes_gcm_decrypt_and_auth] = (unsigned long) cx_aes_gcm_decrypt_and_auth, + [_NR_cx_aes_gcm_encrypt_and_tag] = (unsigned long) cx_aes_gcm_encrypt_and_tag, + [_NR_cx_aes_gcm_finish] = (unsigned long) cx_aes_gcm_finish, + [_NR_cx_aes_gcm_init] = (unsigned long) cx_aes_gcm_init, + [_NR_cx_aes_gcm_set_key] = (unsigned long) cx_aes_gcm_set_key, + [_NR_cx_aes_gcm_start] = (unsigned long) cx_aes_gcm_start, + [_NR_cx_aes_gcm_update_aad] = (unsigned long) cx_aes_gcm_update_aad, + [_NR_cx_aes_gcm_update] = (unsigned long) cx_aes_gcm_update, + [_NR_cx_aes_init_key_no_throw] = (unsigned long) cx_aes_init_key_no_throw, + [_NR_cx_aes_iv_no_throw] = (unsigned long) cx_aes_iv_no_throw, + [_NR_cx_aes_no_throw] = (unsigned long) cx_aes_no_throw, + [_NR_cx_aes_siv_encrypt] = (unsigned long) cx_aes_siv_encrypt, + [_NR_cx_aes_siv_decrypt] = (unsigned long) cx_aes_siv_decrypt, + [_NR_cx_aes_siv_init] = (unsigned long) cx_aes_siv_init, + [_NR_cx_aes_siv_set_key] = (unsigned long) cx_aes_siv_set_key, + [_NR_cx_aes_siv_start] = (unsigned long) cx_aes_siv_start, + [_NR_cx_aes_siv_update_aad] = (unsigned long) cx_aes_siv_update_aad, + [_NR_cx_aes_siv_finish] = (unsigned long) cx_aes_siv_finish, + [_NR_cx_aes_siv_update] = (unsigned long) cx_aes_siv_update, + [_NR_cx_blake2b] = (unsigned long) cx_blake2b, + [_NR_cx_blake2b_final] = (unsigned long) cx_blake2b_final, + [_NR_cx_blake2b_get_output_size] = (unsigned long) cx_blake2b_get_output_size, + [_NR_cx_blake2b_init2_no_throw] = (unsigned long) cx_blake2b_init2_no_throw, + [_NR_cx_blake2b_init_no_throw] = (unsigned long) cx_blake2b_init_no_throw, + [_NR_cx_blake2b_update] = (unsigned long) cx_blake2b_update, + [_NR_cx_cipher_enc_dec] = (unsigned long) cx_cipher_enc_dec, + [_NR_cx_cipher_finish] = (unsigned long) cx_cipher_finish, + [_NR_cx_cipher_init] = (unsigned long) cx_cipher_init, + [_NR_cx_cipher_setiv] = (unsigned long) cx_cipher_setiv, + [_NR_cx_cipher_setkey] = (unsigned long) cx_cipher_setkey, + [_NR_cx_cipher_setup] = (unsigned long) cx_cipher_setup, + [_NR_cx_cipher_set_padding] = (unsigned long) cx_cipher_set_padding, + [_NR_cx_cipher_update] = (unsigned long) cx_cipher_update, + [_NR_cx_cmac] = (unsigned long) cx_cmac, + [_NR_cx_constant_time_eq] = (unsigned long) cx_constant_time_eq, + [_NR_cx_crc16] = (unsigned long) cx_crc16, + [_NR_cx_crc16_update] = (unsigned long) cx_crc16_update, + [_NR_cx_crc32] = (unsigned long) cx_crc32, + [_NR_cx_decode_coord] = (unsigned long) cx_decode_coord, + [_NR_cx_ecdh_no_throw] = (unsigned long) cx_ecdh_no_throw, + [_NR_cx_ecdsa_sign_no_throw] = (unsigned long) cx_ecdsa_sign_no_throw, + [_NR_cx_ecdsa_verify_no_throw] = (unsigned long) cx_ecdsa_verify_no_throw, + [_NR_cx_ecfp_add_point_no_throw] = (unsigned long) cx_ecfp_add_point_no_throw, + [_NR_cx_ecfp_decode_sig_der] = (unsigned long) cx_ecfp_decode_sig_der, + [_NR_cx_ecfp_encode_sig_der] = (unsigned long) cx_ecfp_encode_sig_der, + [_NR_cx_ecfp_generate_pair2_no_throw] = (unsigned long) cx_ecfp_generate_pair2_no_throw, + [_NR_cx_ecfp_generate_pair_no_throw] = (unsigned long) cx_ecfp_generate_pair_no_throw, + [_NR_cx_ecfp_init_private_key_no_throw] = (unsigned long) cx_ecfp_init_private_key_no_throw, + [_NR_cx_ecfp_init_public_key_no_throw] = (unsigned long) cx_ecfp_init_public_key_no_throw, + [_NR_cx_ecfp_scalar_mult_no_throw] = (unsigned long) cx_ecfp_scalar_mult_no_throw, + [_NR_cx_ecschnorr_sign_no_throw] = (unsigned long) cx_ecschnorr_sign_no_throw, + [_NR_cx_ecschnorr_verify] = (unsigned long) cx_ecschnorr_verify, + [_NR_cx_eddsa_get_public_key_internal] = (unsigned long) cx_eddsa_get_public_key_internal, + [_NR_cx_eddsa_get_public_key_no_throw] = (unsigned long) cx_eddsa_get_public_key_no_throw, + [_NR_cx_eddsa_sign_no_throw] = (unsigned long) cx_eddsa_sign_no_throw, + [_NR_cx_eddsa_verify_no_throw] = (unsigned long) cx_eddsa_verify_no_throw, + [_NR_cx_edwards_compress_point_no_throw] = (unsigned long) cx_edwards_compress_point_no_throw, + [_NR_cx_edwards_decompress_point_no_throw] + = (unsigned long) cx_edwards_decompress_point_no_throw, + [_NR_cx_encode_coord] = (unsigned long) cx_encode_coord, + [_NR_cx_hash_final] = (unsigned long) cx_hash_final, + [_NR_cx_hash_get_info] = (unsigned long) cx_hash_get_info, + [_NR_cx_hash_get_size] = (unsigned long) cx_hash_get_size, + [_NR_cx_hash_init] = (unsigned long) cx_hash_init, + [_NR_cx_hash_init_ex] = (unsigned long) cx_hash_init_ex, + [_NR_cx_hash_no_throw] = (unsigned long) cx_hash_no_throw, + [_NR_cx_hash_ripemd160] = (unsigned long) cx_hash_ripemd160, + [_NR_cx_hash_sha256] = (unsigned long) cx_hash_sha256, + [_NR_cx_hash_sha512] = (unsigned long) cx_hash_sha512, + [_NR_cx_hash_update] = (unsigned long) cx_hash_update, + [_NR_cx_hkdf_expand] = (unsigned long) cx_hkdf_expand, + [_NR_cx_hkdf_extract] = (unsigned long) cx_hkdf_extract, + [_NR_cx_hmac_final] = (unsigned long) cx_hmac_final, + [_NR_cx_hmac_init] = (unsigned long) cx_hmac_init, + [_NR_cx_hmac_no_throw] = (unsigned long) cx_hmac_no_throw, + [_NR_cx_hmac_ripemd160_init_no_throw] = (unsigned long) cx_hmac_ripemd160_init_no_throw, + [_NR_cx_hmac_sha224_init] = (unsigned long) cx_hmac_sha224_init, + [_NR_cx_hmac_sha256] = (unsigned long) cx_hmac_sha256, + [_NR_cx_hmac_sha256_init_no_throw] = (unsigned long) cx_hmac_sha256_init_no_throw, + [_NR_cx_hmac_sha384_init] = (unsigned long) cx_hmac_sha384_init, + [_NR_cx_hmac_sha512] = (unsigned long) cx_hmac_sha512, + [_NR_cx_hmac_sha512_init_no_throw] = (unsigned long) cx_hmac_sha512_init_no_throw, + [_NR_cx_hmac_update] = (unsigned long) cx_hmac_update, + [_NR_cx_keccak_init_no_throw] = (unsigned long) cx_keccak_init_no_throw, + [_NR_cx_math_addm_no_throw] = (unsigned long) cx_math_addm_no_throw, + [_NR_cx_math_add_no_throw] = (unsigned long) cx_math_add_no_throw, + [_NR_cx_math_cmp_no_throw] = (unsigned long) cx_math_cmp_no_throw, + [_NR_cx_math_invintm_no_throw] = (unsigned long) cx_math_invintm_no_throw, + [_NR_cx_math_invprimem_no_throw] = (unsigned long) cx_math_invprimem_no_throw, + [_NR_cx_math_is_prime_no_throw] = (unsigned long) cx_math_is_prime_no_throw, + [_NR_cx_math_modm_no_throw] = (unsigned long) cx_math_modm_no_throw, + [_NR_cx_math_multm_no_throw] = (unsigned long) cx_math_multm_no_throw, + [_NR_cx_math_mult_no_throw] = (unsigned long) cx_math_mult_no_throw, + [_NR_cx_math_next_prime_no_throw] = (unsigned long) cx_math_next_prime_no_throw, + [_NR_cx_math_powm_no_throw] = (unsigned long) cx_math_powm_no_throw, + [_NR_cx_math_subm_no_throw] = (unsigned long) cx_math_subm_no_throw, + [_NR_cx_math_sub_no_throw] = (unsigned long) cx_math_sub_no_throw, + [_NR_cx_memxor] = (unsigned long) cx_memxor, + [_NR_cx_pbkdf2_hmac] = (unsigned long) cx_pbkdf2_hmac, + [_NR_cx_pbkdf2_no_throw] = (unsigned long) cx_pbkdf2_no_throw, + [_NR_cx_ripemd160_final] = (unsigned long) cx_ripemd160_final, + [_NR_cx_ripemd160_init_no_throw] = (unsigned long) cx_ripemd160_init_no_throw, + [_NR_cx_ripemd160_update] = (unsigned long) cx_ripemd160_update, + [_NR_cx_rng_no_throw] = (unsigned long) cx_rng_no_throw, + [_NR_cx_rng_rfc6979] = (unsigned long) cx_rng_rfc6979, + [_NR_cx_rng_rfc6979_init] = (unsigned long) cx_rng_rfc6979_init, + [_NR_cx_rng_rfc6979_next] = (unsigned long) cx_rng_rfc6979_next, + [_NR_cx_rng_u32_range_func] = (unsigned long) cx_rng_u32_range_func, + [_NR_cx_sha224_init_no_throw] = (unsigned long) cx_sha224_init_no_throw, + [_NR_cx_sha256_final] = (unsigned long) cx_sha256_final, + [_NR_cx_sha256_init_no_throw] = (unsigned long) cx_sha256_init_no_throw, + [_NR_cx_sha256_update] = (unsigned long) cx_sha256_update, + [_NR_cx_sha384_init_no_throw] = (unsigned long) cx_sha384_init_no_throw, + [_NR_cx_sha3_final] = (unsigned long) cx_sha3_final, + [_NR_cx_sha3_get_output_size] = (unsigned long) cx_sha3_get_output_size, + [_NR_cx_sha3_init_no_throw] = (unsigned long) cx_sha3_init_no_throw, + [_NR_cx_sha3_update] = (unsigned long) cx_sha3_update, + [_NR_cx_sha3_xof_init_no_throw] = (unsigned long) cx_sha3_xof_init_no_throw, + [_NR_cx_sha512_final] = (unsigned long) cx_sha512_final, + [_NR_cx_sha512_init_no_throw] = (unsigned long) cx_sha512_init_no_throw, + [_NR_cx_sha512_update] = (unsigned long) cx_sha512_update, + [_NR_cx_shake128_init_no_throw] = (unsigned long) cx_shake128_init_no_throw, + [_NR_cx_shake256_init_no_throw] = (unsigned long) cx_shake256_init_no_throw, + [_NR_cx_swap_buffer32] = (unsigned long) cx_swap_buffer32, + [_NR_cx_swap_buffer64] = (unsigned long) cx_swap_buffer64, + [_NR_cx_swap_uint32] = (unsigned long) cx_swap_uint32, + [_NR_cx_swap_uint64] = (unsigned long) cx_swap_uint64, + [_NR_cx_x25519] = (unsigned long) cx_x25519, + [_NR_cx_x448] = (unsigned long) cx_x448, }; diff --git a/lib_cxng/src/cx_groestl.h b/lib_cxng/src/cx_groestl.h index 25f316666..7a0bfe0ec 100644 --- a/lib_cxng/src/cx_groestl.h +++ b/lib_cxng/src/cx_groestl.h @@ -14,6 +14,6 @@ struct cx_xgroestl_s { }; typedef struct cx_xgroestl_s cx_xgroestl_t; -#endif // CX_GROESTL_H +#endif // CX_GROESTL_H -#endif // HAVE_GROESTL +#endif // HAVE_GROESTL diff --git a/lib_cxng/src/cx_hash.c b/lib_cxng/src/cx_hash.c index 837a32315..fcd015f5b 100644 --- a/lib_cxng/src/cx_hash.c +++ b/lib_cxng/src/cx_hash.c @@ -1,20 +1,20 @@ /******************************************************************************* -* Ledger Nano S - Secure firmware -* (c) 2022 Ledger -* -* Licensed under the Apache License, Version 2.0 (the "License"); -* you may not use this file except in compliance with the License. -* You may obtain a copy of the License at -* -* http://www.apache.org/licenses/LICENSE-2.0 -* -* Unless required by applicable law or agreed to in writing, software -* distributed under the License is distributed on an "AS IS" BASIS, -* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -* See the License for the specific language governing permissions and -* limitations under the License. -********************************************************************************/ + * Ledger Nano S - Secure firmware + * (c) 2022 Ledger + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + ********************************************************************************/ #ifdef HAVE_HASH @@ -33,123 +33,135 @@ #include "errors.h" #include "exceptions.h" -const cx_hash_info_t *cx_hash_get_info(cx_md_t md_type) { - switch (md_type) { +const cx_hash_info_t *cx_hash_get_info(cx_md_t md_type) +{ + switch (md_type) { #ifdef HAVE_SHA256 - case CX_SHA256: - return &cx_sha256_info; + case CX_SHA256: + return &cx_sha256_info; #endif #ifdef HAVE_RIPEMD160 - case CX_RIPEMD160: - return &cx_ripemd160_info; + case CX_RIPEMD160: + return &cx_ripemd160_info; #endif #ifdef HAVE_SHA224 - case CX_SHA224: - return &cx_sha224_info; + case CX_SHA224: + return &cx_sha224_info; #endif #ifdef HAVE_SHA384 - case CX_SHA384: - return &cx_sha384_info; + case CX_SHA384: + return &cx_sha384_info; #endif #ifdef HAVE_SHA512 - case CX_SHA512: - return &cx_sha512_info; + case CX_SHA512: + return &cx_sha512_info; #endif #ifdef HAVE_SHA3 - case CX_SHA3: - case CX_SHA3_256: - case CX_SHA3_512: - return &cx_sha3_info; - case CX_KECCAK: - return &cx_keccak_info; - case CX_SHAKE128: - return &cx_shake128_info; - case CX_SHAKE256: - return &cx_shake256_info; + case CX_SHA3: + case CX_SHA3_256: + case CX_SHA3_512: + return &cx_sha3_info; + case CX_KECCAK: + return &cx_keccak_info; + case CX_SHAKE128: + return &cx_shake128_info; + case CX_SHAKE256: + return &cx_shake256_info; #endif #ifdef HAVE_BLAKE2 - case CX_BLAKE2B: - return &cx_blake2b_info; + case CX_BLAKE2B: + return &cx_blake2b_info; #endif - default: - return NULL; - } + default: + return NULL; + } } -size_t cx_hash_get_size(const cx_hash_t *ctx) { - const cx_hash_info_t *info = ctx->info; - if (info->output_size) { - return info->output_size; - } - return info->output_size_func(ctx); +size_t cx_hash_get_size(const cx_hash_t *ctx) +{ + const cx_hash_info_t *info = ctx->info; + if (info->output_size) { + return info->output_size; + } + return info->output_size_func(ctx); } -cx_err_t cx_hash_init(cx_hash_t *ctx, cx_md_t md_type) { - const cx_hash_info_t *info = cx_hash_get_info(md_type); - if (info == NULL) { - return CX_INVALID_PARAMETER; - } - if (info->output_size == 0) { /* variable output size, must use cx_hash_init_ex */ - return CX_INVALID_PARAMETER; - } - info->init_func(ctx); - return CX_OK; +cx_err_t cx_hash_init(cx_hash_t *ctx, cx_md_t md_type) +{ + const cx_hash_info_t *info = cx_hash_get_info(md_type); + if (info == NULL) { + return CX_INVALID_PARAMETER; + } + if (info->output_size == 0) { /* variable output size, must use cx_hash_init_ex */ + return CX_INVALID_PARAMETER; + } + info->init_func(ctx); + return CX_OK; } -cx_err_t cx_hash_init_ex(cx_hash_t *ctx, cx_md_t md_type, size_t output_size) { - const cx_hash_info_t *info = cx_hash_get_info(md_type); - if (info == NULL) { - return CX_INVALID_PARAMETER; - } - if (info->output_size != 0) { - if (info->output_size != output_size) { - return CX_INVALID_PARAMETER; +cx_err_t cx_hash_init_ex(cx_hash_t *ctx, cx_md_t md_type, size_t output_size) +{ + const cx_hash_info_t *info = cx_hash_get_info(md_type); + if (info == NULL) { + return CX_INVALID_PARAMETER; + } + if (info->output_size != 0) { + if (info->output_size != output_size) { + return CX_INVALID_PARAMETER; + } + return cx_hash_init(ctx, md_type); } - return cx_hash_init(ctx, md_type); - } - return info->init_ex_func(ctx, output_size * 8); + return info->init_ex_func(ctx, output_size * 8); } -cx_err_t cx_hash_update(cx_hash_t *ctx, const uint8_t *data, size_t len) { - const cx_hash_info_t *info = ctx->info; - return info->update_func(ctx, data, len); +cx_err_t cx_hash_update(cx_hash_t *ctx, const uint8_t *data, size_t len) +{ + const cx_hash_info_t *info = ctx->info; + return info->update_func(ctx, data, len); } -cx_err_t cx_hash_final(cx_hash_t *ctx, uint8_t *digest) { - const cx_hash_info_t *info = ctx->info; - info->finish_func(ctx, digest); - return CX_OK; +cx_err_t cx_hash_final(cx_hash_t *ctx, uint8_t *digest) +{ + const cx_hash_info_t *info = ctx->info; + info->finish_func(ctx, digest); + return CX_OK; } -cx_err_t cx_hash_no_throw(cx_hash_t *hash, uint32_t mode, const uint8_t *in, size_t len, uint8_t *out, size_t out_len) { - unsigned int digest_len; - cx_err_t error; - - // --- init locals --- - digest_len = (unsigned int)cx_hash_get_size(hash); - CX_CHECK(cx_hash_update(hash, in, len)); - - if (mode & CX_LAST) { - if (out_len < digest_len) { - return INVALID_PARAMETER; +cx_err_t cx_hash_no_throw(cx_hash_t *hash, + uint32_t mode, + const uint8_t *in, + size_t len, + uint8_t *out, + size_t out_len) +{ + unsigned int digest_len; + cx_err_t error; + + // --- init locals --- + digest_len = (unsigned int) cx_hash_get_size(hash); + CX_CHECK(cx_hash_update(hash, in, len)); + + if (mode & CX_LAST) { + if (out_len < digest_len) { + return INVALID_PARAMETER; + } + CX_CHECK(cx_hash_final(hash, out)); } - CX_CHECK(cx_hash_final(hash, out)); - } - end: - return error; +end: + return error; } void cx_hash_destroy(cx_hash_t *hash_ctx) { - explicit_bzero(hash_ctx, hash_ctx->info->ctx_size); + explicit_bzero(hash_ctx, hash_ctx->info->ctx_size); } -#endif // HAVE_HASH +#endif // HAVE_HASH diff --git a/lib_cxng/src/cx_hash.h b/lib_cxng/src/cx_hash.h index a3c6a405b..9eea396f3 100644 --- a/lib_cxng/src/cx_hash.h +++ b/lib_cxng/src/cx_hash.h @@ -1,20 +1,20 @@ /******************************************************************************* -* Ledger Nano S - Secure firmware -* (c) 2022 Ledger -* -* Licensed under the Apache License, Version 2.0 (the "License"); -* you may not use this file except in compliance with the License. -* You may obtain a copy of the License at -* -* http://www.apache.org/licenses/LICENSE-2.0 -* -* Unless required by applicable law or agreed to in writing, software -* distributed under the License is distributed on an "AS IS" BASIS, -* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -* See the License for the specific language governing permissions and -* limitations under the License. -********************************************************************************/ + * Ledger Nano S - Secure firmware + * (c) 2022 Ledger + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + ********************************************************************************/ #ifdef HAVE_HASH @@ -32,12 +32,17 @@ #define SHA512_BLOCK_SIZE 128 #endif -//#warning reduce MAX_HASH_SIZE and MAX_HASH_BLOCK_SIZE according to HAVE_xxx -#define MAX_HASH_SIZE 128 +// #warning reduce MAX_HASH_SIZE and MAX_HASH_BLOCK_SIZE according to HAVE_xxx +#define MAX_HASH_SIZE 128 #define MAX_HASH_BLOCK_SIZE 128 #ifdef HAVE_BLAKE2 -cx_err_t cx_blake2b(cx_hash_t *hash, uint32_t mode, const uint8_t *in, size_t in_len, uint8_t *out, size_t out_len); +cx_err_t cx_blake2b(cx_hash_t *hash, + uint32_t mode, + const uint8_t *in, + size_t in_len, + uint8_t *out, + size_t out_len); #endif const cx_hash_info_t *cx_hash_get_info(cx_md_t md_type); @@ -49,4 +54,4 @@ void cx_hash_destroy(cx_hash_t *hash_ctx); #endif -#endif // HAVE_HASH +#endif // HAVE_HASH diff --git a/lib_cxng/src/cx_hkdf.c b/lib_cxng/src/cx_hkdf.c index 54095c8a0..2bbf85ee6 100644 --- a/lib_cxng/src/cx_hkdf.c +++ b/lib_cxng/src/cx_hkdf.c @@ -9,53 +9,63 @@ // HMAC-Based Key Kerivation Function defined at https://tools.ietf.org/html/rfc5869 // Used to implement the EIP-2333 for BLS12-381 key generation -void cx_hkdf_extract(const cx_md_t hash_id, const unsigned char* ikm, unsigned int ikm_len, - unsigned char *salt, unsigned int salt_len, unsigned char *prk) { - cx_hmac_t *hmac_ctx; - const cx_hash_info_t *hash_info; - size_t md_len; - - hash_info = cx_hash_get_info(hash_id); - md_len = hash_info->output_size; - - hmac_ctx = &G_cx.hmac; - - if (salt == NULL) { - memset(hmac_ctx->key, 0 , md_len); - salt = hmac_ctx->key; - salt_len = md_len; - } - cx_hmac_init(hmac_ctx, hash_id, salt, salt_len); - cx_hmac_update(hmac_ctx, ikm, ikm_len); - cx_hmac_final(hmac_ctx, prk, &md_len); +void cx_hkdf_extract(const cx_md_t hash_id, + const unsigned char *ikm, + unsigned int ikm_len, + unsigned char *salt, + unsigned int salt_len, + unsigned char *prk) +{ + cx_hmac_t *hmac_ctx; + const cx_hash_info_t *hash_info; + size_t md_len; + hash_info = cx_hash_get_info(hash_id); + md_len = hash_info->output_size; + + hmac_ctx = &G_cx.hmac; + + if (salt == NULL) { + memset(hmac_ctx->key, 0, md_len); + salt = hmac_ctx->key; + salt_len = md_len; + } + cx_hmac_init(hmac_ctx, hash_id, salt, salt_len); + cx_hmac_update(hmac_ctx, ikm, ikm_len); + cx_hmac_final(hmac_ctx, prk, &md_len); } -void cx_hkdf_expand(const cx_md_t hash_id, const unsigned char *prk, unsigned int prk_len, unsigned char *info, - unsigned int info_len, unsigned char *okm, unsigned int okm_len) { - unsigned char i; - unsigned int offset = 0; - unsigned char T[MAX_HASH_SIZE]; - cx_hmac_t *hmac_ctx; - const cx_hash_info_t *hash_info; - size_t md_len; +void cx_hkdf_expand(const cx_md_t hash_id, + const unsigned char *prk, + unsigned int prk_len, + unsigned char *info, + unsigned int info_len, + unsigned char *okm, + unsigned int okm_len) +{ + unsigned char i; + unsigned int offset = 0; + unsigned char T[MAX_HASH_SIZE]; + cx_hmac_t *hmac_ctx; + const cx_hash_info_t *hash_info; + size_t md_len; - hash_info = cx_hash_get_info(hash_id); - md_len = hash_info->output_size; + hash_info = cx_hash_get_info(hash_id); + md_len = hash_info->output_size; - hmac_ctx = &G_cx.hmac; + hmac_ctx = &G_cx.hmac; - for (i = 1; okm_len > 0; i++) { - cx_hmac_init(hmac_ctx, hash_id, prk, prk_len); - if (i > 1) { - cx_hmac_update(hmac_ctx, T, offset); + for (i = 1; okm_len > 0; i++) { + cx_hmac_init(hmac_ctx, hash_id, prk, prk_len); + if (i > 1) { + cx_hmac_update(hmac_ctx, T, offset); + } + cx_hmac_update(hmac_ctx, info, info_len); + cx_hmac_update(hmac_ctx, &i, sizeof(i)); + cx_hmac_final(hmac_ctx, T, &md_len); + offset = (okm_len < md_len) ? okm_len : md_len; + memcpy(okm + (i - 1) * md_len, T, offset); + okm_len -= offset; } - cx_hmac_update(hmac_ctx, info, info_len); - cx_hmac_update(hmac_ctx, &i, sizeof(i)); - cx_hmac_final(hmac_ctx, T, &md_len); - offset = ( okm_len < md_len ) ? okm_len : md_len; - memcpy(okm + (i-1) * md_len, T, offset); - okm_len -= offset; - } } -#endif // HAVE_HMAC +#endif // HAVE_HMAC diff --git a/lib_cxng/src/cx_hkdf.h b/lib_cxng/src/cx_hkdf.h index af573c3d0..ca488b8a5 100644 --- a/lib_cxng/src/cx_hkdf.h +++ b/lib_cxng/src/cx_hkdf.h @@ -3,9 +3,18 @@ #include "lcx_hash.h" -void cx_hkdf_extract(const cx_md_t hash_id, const unsigned char *ikm, unsigned int ikm_len, unsigned char *salt, - unsigned int salt_len, unsigned char *prk); -void cx_hkdf_expand(const cx_md_t hash_id, const unsigned char *prk, unsigned int prk_len, unsigned char *info, - unsigned int info_len, unsigned char *okm, unsigned int okm_len); +void cx_hkdf_extract(const cx_md_t hash_id, + const unsigned char *ikm, + unsigned int ikm_len, + unsigned char *salt, + unsigned int salt_len, + unsigned char *prk); +void cx_hkdf_expand(const cx_md_t hash_id, + const unsigned char *prk, + unsigned int prk_len, + unsigned char *info, + unsigned int info_len, + unsigned char *okm, + unsigned int okm_len); -#endif // CX_HKDF_H +#endif // CX_HKDF_H diff --git a/lib_cxng/src/cx_hmac.c b/lib_cxng/src/cx_hmac.c index 495e24f2b..afb7be322 100644 --- a/lib_cxng/src/cx_hmac.c +++ b/lib_cxng/src/cx_hmac.c @@ -1,20 +1,20 @@ /******************************************************************************* -* Ledger Nano S - Secure firmware -* (c) 2022 Ledger -* -* Licensed under the Apache License, Version 2.0 (the "License"); -* you may not use this file except in compliance with the License. -* You may obtain a copy of the License at -* -* http://www.apache.org/licenses/LICENSE-2.0 -* -* Unless required by applicable law or agreed to in writing, software -* distributed under the License is distributed on an "AS IS" BASIS, -* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -* See the License for the specific language governing permissions and -* limitations under the License. -********************************************************************************/ + * Ledger Nano S - Secure firmware + * (c) 2022 Ledger + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + ********************************************************************************/ #ifdef HAVE_HMAC @@ -30,178 +30,201 @@ #define IPAD 0x36u #define OPAD 0x5cu -static size_t cx_get_block_size(cx_md_t md) { - const cx_hash_info_t *info = cx_hash_get_info(md); - if (info == NULL) { - return 0; - } - return info->block_size; +static size_t cx_get_block_size(cx_md_t md) +{ + const cx_hash_info_t *info = cx_hash_get_info(md); + if (info == NULL) { + return 0; + } + return info->block_size; } -static cx_md_t cx_get_algorithm(cx_hmac_t *ctx) { - return ctx->hash_ctx.info->md_type; +static cx_md_t cx_get_algorithm(cx_hmac_t *ctx) +{ + return ctx->hash_ctx.info->md_type; } -static bool cx_is_allowed_digest(cx_md_t md_type) { - const cx_md_t allowed_algorithms[] = { +static bool cx_is_allowed_digest(cx_md_t md_type) +{ + const cx_md_t allowed_algorithms[] = { #ifdef HAVE_SHA224 - CX_SHA224, + CX_SHA224, #endif #ifdef HAVE_SHA256 - CX_SHA256, + CX_SHA256, #endif #ifdef HAVE_SHA384 - CX_SHA384, + CX_SHA384, #endif #ifdef HAVE_SHA512 - CX_SHA512, + CX_SHA512, #endif #ifdef HAVE_RIPEMD160 - CX_RIPEMD160, + CX_RIPEMD160, #endif - }; - for (unsigned int i = 0; i < sizeof(allowed_algorithms) / sizeof(allowed_algorithms[0]); i++) { - if (allowed_algorithms[i] == md_type) { - return true; + }; + for (unsigned int i = 0; i < sizeof(allowed_algorithms) / sizeof(allowed_algorithms[0]); i++) { + if (allowed_algorithms[i] == md_type) { + return true; + } } - } - return false; + return false; } -cx_err_t cx_hmac_init(cx_hmac_t *ctx, cx_md_t hash_id, const uint8_t *key, size_t key_len) { - cx_hash_t *hash_ctx; - - if ((ctx == NULL) || - (!cx_is_allowed_digest(hash_id)) || - (key == NULL && key_len != 0)) { - return CX_INVALID_PARAMETER; - } - - hash_ctx = &ctx->hash_ctx, - memset(ctx, 0, sizeof(cx_hmac_t)); - size_t block_size = cx_get_block_size(hash_id); - - if (key) { - if (key_len > block_size) { - cx_hash_init(hash_ctx, hash_id); - cx_hash_update(hash_ctx, key, key_len); - cx_hash_final(hash_ctx, ctx->key); - } else { - memcpy(ctx->key, key, key_len); +cx_err_t cx_hmac_init(cx_hmac_t *ctx, cx_md_t hash_id, const uint8_t *key, size_t key_len) +{ + cx_hash_t *hash_ctx; + + if ((ctx == NULL) || (!cx_is_allowed_digest(hash_id)) || (key == NULL && key_len != 0)) { + return CX_INVALID_PARAMETER; } - for (unsigned int i = 0; i < block_size; i++) { - ctx->key[i] ^= IPAD; + hash_ctx = &ctx->hash_ctx, memset(ctx, 0, sizeof(cx_hmac_t)); + size_t block_size = cx_get_block_size(hash_id); + + if (key) { + if (key_len > block_size) { + cx_hash_init(hash_ctx, hash_id); + cx_hash_update(hash_ctx, key, key_len); + cx_hash_final(hash_ctx, ctx->key); + } + else { + memcpy(ctx->key, key, key_len); + } + + for (unsigned int i = 0; i < block_size; i++) { + ctx->key[i] ^= IPAD; + } } - } - cx_hash_init(hash_ctx, hash_id); - cx_hash_update(hash_ctx, ctx->key, block_size); - return CX_OK; + cx_hash_init(hash_ctx, hash_id); + cx_hash_update(hash_ctx, ctx->key, block_size); + return CX_OK; } -cx_err_t cx_hmac_update(cx_hmac_t *ctx, const uint8_t *data, size_t data_len) { - if (data_len == 0) { - return CX_OK; - } - return cx_hash_update(&ctx->hash_ctx, data, data_len); +cx_err_t cx_hmac_update(cx_hmac_t *ctx, const uint8_t *data, size_t data_len) +{ + if (data_len == 0) { + return CX_OK; + } + return cx_hash_update(&ctx->hash_ctx, data, data_len); } -cx_err_t cx_hmac_final(cx_hmac_t *ctx, uint8_t *out, size_t *out_len) { - uint8_t inner_hash[MAX_HASH_SIZE]; - uint8_t hkey[MAX_HASH_BLOCK_SIZE]; +cx_err_t cx_hmac_final(cx_hmac_t *ctx, uint8_t *out, size_t *out_len) +{ + uint8_t inner_hash[MAX_HASH_SIZE]; + uint8_t hkey[MAX_HASH_BLOCK_SIZE]; - cx_hash_t *hash_ctx = &ctx->hash_ctx; + cx_hash_t *hash_ctx = &ctx->hash_ctx; - cx_md_t hash_algorithm = cx_get_algorithm(ctx); - size_t block_size = cx_get_block_size(hash_algorithm); - size_t hash_output_size = cx_hash_get_size(hash_ctx); + cx_md_t hash_algorithm = cx_get_algorithm(ctx); + size_t block_size = cx_get_block_size(hash_algorithm); + size_t hash_output_size = cx_hash_get_size(hash_ctx); - cx_hash_final(hash_ctx, inner_hash); + cx_hash_final(hash_ctx, inner_hash); - // hash key xor 5c (and 36 to remove prepadding at init) - memcpy(hkey, ctx->key, block_size); - for (unsigned int i = 0; i < block_size; i++) { - hkey[i] ^= OPAD ^ IPAD; - } + // hash key xor 5c (and 36 to remove prepadding at init) + memcpy(hkey, ctx->key, block_size); + for (unsigned int i = 0; i < block_size; i++) { + hkey[i] ^= OPAD ^ IPAD; + } - cx_hash_init(hash_ctx, hash_algorithm); - cx_hash_update(hash_ctx, hkey, block_size); - cx_hash_update(hash_ctx, inner_hash, hash_output_size); - cx_hash_final(hash_ctx, hkey); + cx_hash_init(hash_ctx, hash_algorithm); + cx_hash_update(hash_ctx, hkey, block_size); + cx_hash_update(hash_ctx, inner_hash, hash_output_size); + cx_hash_final(hash_ctx, hkey); - // length result - if (*out_len >= hash_output_size) { - *out_len = hash_output_size; - } - memcpy(out, hkey, *out_len); - return CX_OK; + // length result + if (*out_len >= hash_output_size) { + *out_len = hash_output_size; + } + memcpy(out, hkey, *out_len); + return CX_OK; } #ifdef HAVE_SHA224 -cx_err_t cx_hmac_sha224_init(cx_hmac_sha256_t *hmac, const uint8_t *key, unsigned int key_len) { - return cx_hmac_init((cx_hmac_t *)hmac, CX_SHA224, key, key_len); +cx_err_t cx_hmac_sha224_init(cx_hmac_sha256_t *hmac, const uint8_t *key, unsigned int key_len) +{ + return cx_hmac_init((cx_hmac_t *) hmac, CX_SHA224, key, key_len); } #endif #ifdef HAVE_SHA256 -cx_err_t cx_hmac_sha256_init_no_throw(cx_hmac_sha256_t *hmac, const uint8_t *key, size_t key_len) { - return cx_hmac_init((cx_hmac_t *)hmac, CX_SHA256, key, key_len); +cx_err_t cx_hmac_sha256_init_no_throw(cx_hmac_sha256_t *hmac, const uint8_t *key, size_t key_len) +{ + return cx_hmac_init((cx_hmac_t *) hmac, CX_SHA256, key, key_len); } #endif #ifdef HAVE_SHA384 -cx_err_t cx_hmac_sha384_init(cx_hmac_sha512_t *hmac, const uint8_t *key, unsigned int key_len) { - return cx_hmac_init((cx_hmac_t *)hmac, CX_SHA384, key, key_len); +cx_err_t cx_hmac_sha384_init(cx_hmac_sha512_t *hmac, const uint8_t *key, unsigned int key_len) +{ + return cx_hmac_init((cx_hmac_t *) hmac, CX_SHA384, key, key_len); } #endif #ifdef HAVE_SHA512 -cx_err_t cx_hmac_sha512_init_no_throw(cx_hmac_sha512_t *hmac, const uint8_t *key, size_t key_len) { - return cx_hmac_init((cx_hmac_t *)hmac, CX_SHA512, key, key_len); +cx_err_t cx_hmac_sha512_init_no_throw(cx_hmac_sha512_t *hmac, const uint8_t *key, size_t key_len) +{ + return cx_hmac_init((cx_hmac_t *) hmac, CX_SHA512, key, key_len); } #endif #ifdef HAVE_RIPEMD160 -cx_err_t cx_hmac_ripemd160_init_no_throw(cx_hmac_ripemd160_t *hmac, const uint8_t *key, size_t key_len) { - return cx_hmac_init((cx_hmac_t *)hmac, CX_RIPEMD160, key, key_len); +cx_err_t cx_hmac_ripemd160_init_no_throw(cx_hmac_ripemd160_t *hmac, + const uint8_t *key, + size_t key_len) +{ + return cx_hmac_init((cx_hmac_t *) hmac, CX_RIPEMD160, key, key_len); } #endif -cx_err_t cx_hmac_no_throw(cx_hmac_t *hmac, uint32_t mode, const uint8_t *in, size_t len, uint8_t *out, size_t out_len) { - size_t output_size = 0; - cx_err_t error = CX_OK; - - if (in == NULL && len != 0) { - return CX_INVALID_PARAMETER; - } - if (out == NULL && out_len != 0) { - return CX_INVALID_PARAMETER; - } +cx_err_t cx_hmac_no_throw(cx_hmac_t *hmac, + uint32_t mode, + const uint8_t *in, + size_t len, + uint8_t *out, + size_t out_len) +{ + size_t output_size = 0; + cx_err_t error = CX_OK; + + if (in == NULL && len != 0) { + return CX_INVALID_PARAMETER; + } + if (out == NULL && out_len != 0) { + return CX_INVALID_PARAMETER; + } - if (in != NULL) { - CX_CHECK(cx_hmac_update(hmac, in, len)); - } + if (in != NULL) { + CX_CHECK(cx_hmac_update(hmac, in, len)); + } - if (mode & CX_LAST) { - output_size = out_len; - cx_hmac_final(hmac, out, &output_size); + if (mode & CX_LAST) { + output_size = out_len; + cx_hmac_final(hmac, out, &output_size); - if (!(mode & CX_NO_REINIT)) { - cx_hmac_init(hmac, cx_get_algorithm(hmac), NULL, 0); + if (!(mode & CX_NO_REINIT)) { + cx_hmac_init(hmac, cx_get_algorithm(hmac), NULL, 0); + } } - } - end: - return error; +end: + return error; } #ifdef HAVE_SHA256 -size_t cx_hmac_sha256(const uint8_t *key, size_t key_len, const uint8_t *in, size_t len, uint8_t *out, size_t out_len) { - size_t mac_len = out_len; - cx_hmac_init(&G_cx.hmac, CX_SHA256, key, key_len); - cx_hmac_update(&G_cx.hmac, in, len); - cx_hmac_final(&G_cx.hmac, out, &mac_len); - explicit_bzero(&G_cx.hmac, sizeof(cx_hmac_sha256_t)); - return mac_len; +size_t cx_hmac_sha256(const uint8_t *key, + size_t key_len, + const uint8_t *in, + size_t len, + uint8_t *out, + size_t out_len) +{ + size_t mac_len = out_len; + cx_hmac_init(&G_cx.hmac, CX_SHA256, key, key_len); + cx_hmac_update(&G_cx.hmac, in, len); + cx_hmac_final(&G_cx.hmac, out, &mac_len); + explicit_bzero(&G_cx.hmac, sizeof(cx_hmac_sha256_t)); + return mac_len; } #endif @@ -210,15 +233,16 @@ size_t cx_hmac_sha512(const uint8_t *key, size_t key_len, const uint8_t *in, size_t len, - uint8_t * out, - size_t out_len) { - size_t mac_len = out_len; - cx_hmac_init(&G_cx.hmac, CX_SHA512, key, key_len); - cx_hmac_update(&G_cx.hmac, in, len); - cx_hmac_final(&G_cx.hmac, out, &mac_len); - explicit_bzero(&G_cx.hmac, sizeof(cx_hmac_sha512_t)); - return mac_len; + uint8_t *out, + size_t out_len) +{ + size_t mac_len = out_len; + cx_hmac_init(&G_cx.hmac, CX_SHA512, key, key_len); + cx_hmac_update(&G_cx.hmac, in, len); + cx_hmac_final(&G_cx.hmac, out, &mac_len); + explicit_bzero(&G_cx.hmac, sizeof(cx_hmac_sha512_t)); + return mac_len; } #endif -#endif // HAVE_HMAC +#endif // HAVE_HMAC diff --git a/lib_cxng/src/cx_hmac.h b/lib_cxng/src/cx_hmac.h index 56b8765ec..9c00f435c 100644 --- a/lib_cxng/src/cx_hmac.h +++ b/lib_cxng/src/cx_hmac.h @@ -1,20 +1,20 @@ /******************************************************************************* -* Ledger Nano S - Secure firmware -* (c) 2022 Ledger -* -* Licensed under the Apache License, Version 2.0 (the "License"); -* you may not use this file except in compliance with the License. -* You may obtain a copy of the License at -* -* http://www.apache.org/licenses/LICENSE-2.0 -* -* Unless required by applicable law or agreed to in writing, software -* distributed under the License is distributed on an "AS IS" BASIS, -* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -* See the License for the specific language governing permissions and -* limitations under the License. -********************************************************************************/ + * Ledger Nano S - Secure firmware + * (c) 2022 Ledger + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + ********************************************************************************/ #ifdef HAVE_HMAC @@ -23,6 +23,6 @@ #include "lcx_hmac.h" -#endif // CX_HMAC_H +#endif // CX_HMAC_H #endif diff --git a/lib_cxng/src/cx_math.c b/lib_cxng/src/cx_math.c index 793799aa8..cf2d75822 100644 --- a/lib_cxng/src/cx_math.c +++ b/lib_cxng/src/cx_math.c @@ -1,232 +1,261 @@ /******************************************************************************* -* Ledger Nano S - Secure firmware -* (c) 2022 Ledger -* -* Licensed under the Apache License, Version 2.0 (the "License"); -* you may not use this file except in compliance with the License. -* You may obtain a copy of the License at -* -* http://www.apache.org/licenses/LICENSE-2.0 -* -* Unless required by applicable law or agreed to in writing, software -* distributed under the License is distributed on an "AS IS" BASIS, -* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -* See the License for the specific language governing permissions and -* limitations under the License. -********************************************************************************/ + * Ledger Nano S - Secure firmware + * (c) 2022 Ledger + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + ********************************************************************************/ #ifdef HAVE_MATH #include "cx_math.h" #include "cx_utils.h" +cx_err_t cx_math_cmp_no_throw(const uint8_t *a, const uint8_t *b, size_t length, int *diff) +{ + cx_err_t error; + cx_bn_t bn_a, bn_b; -cx_err_t cx_math_cmp_no_throw ( const uint8_t * a, const uint8_t * b, size_t length, int *diff ) { - cx_err_t error; - cx_bn_t bn_a, bn_b; - - CX_CHECK(cx_bn_lock(length, 0)); - CX_CHECK(cx_bn_alloc_init(&bn_a, length, a, length)); - CX_CHECK(cx_bn_alloc_init(&bn_b, length, b, length)); - CX_CHECK(cx_bn_cmp(bn_a, bn_b, diff)); - cx_bn_unlock(); + CX_CHECK(cx_bn_lock(length, 0)); + CX_CHECK(cx_bn_alloc_init(&bn_a, length, a, length)); + CX_CHECK(cx_bn_alloc_init(&bn_b, length, b, length)); + CX_CHECK(cx_bn_cmp(bn_a, bn_b, diff)); + cx_bn_unlock(); end: - return error; + return error; } -cx_err_t cx_math_add_no_throw( uint8_t * r, const uint8_t * a, const uint8_t * b, size_t len ) { - cx_bn_t bn_a, bn_b, bn_r; - cx_err_t error; +cx_err_t cx_math_add_no_throw(uint8_t *r, const uint8_t *a, const uint8_t *b, size_t len) +{ + cx_bn_t bn_a, bn_b, bn_r; + cx_err_t error; - CX_CHECK(cx_bn_lock(len, 0)); - CX_CHECK(cx_bn_alloc(&bn_r, len)); - CX_CHECK(cx_bn_alloc_init(&bn_a, len, a, len)); - CX_CHECK(cx_bn_alloc_init(&bn_b, len, b, len)); - CX_CHECK_IGNORE_CARRY(cx_bn_add(bn_r, bn_a, bn_b)); - CX_CHECK(cx_bn_export(bn_r, r, len)); - cx_bn_unlock(); + CX_CHECK(cx_bn_lock(len, 0)); + CX_CHECK(cx_bn_alloc(&bn_r, len)); + CX_CHECK(cx_bn_alloc_init(&bn_a, len, a, len)); + CX_CHECK(cx_bn_alloc_init(&bn_b, len, b, len)); + CX_CHECK_IGNORE_CARRY(cx_bn_add(bn_r, bn_a, bn_b)); + CX_CHECK(cx_bn_export(bn_r, r, len)); + cx_bn_unlock(); end: - return error; + return error; } -cx_err_t cx_math_sub_no_throw( uint8_t * r, const uint8_t * a, const uint8_t * b, size_t len ) { - cx_bn_t bn_a, bn_b, bn_r; - cx_err_t error; +cx_err_t cx_math_sub_no_throw(uint8_t *r, const uint8_t *a, const uint8_t *b, size_t len) +{ + cx_bn_t bn_a, bn_b, bn_r; + cx_err_t error; - CX_CHECK(cx_bn_lock(len, 0)); - CX_CHECK(cx_bn_alloc(&bn_r, len)); - CX_CHECK(cx_bn_alloc_init(&bn_a, len, a, len)); - CX_CHECK(cx_bn_alloc_init(&bn_b, len, b, len)); - CX_CHECK_IGNORE_CARRY(cx_bn_sub(bn_r, bn_a, bn_b)); - CX_CHECK(cx_bn_export(bn_r, r, len)); - cx_bn_unlock(); + CX_CHECK(cx_bn_lock(len, 0)); + CX_CHECK(cx_bn_alloc(&bn_r, len)); + CX_CHECK(cx_bn_alloc_init(&bn_a, len, a, len)); + CX_CHECK(cx_bn_alloc_init(&bn_b, len, b, len)); + CX_CHECK_IGNORE_CARRY(cx_bn_sub(bn_r, bn_a, bn_b)); + CX_CHECK(cx_bn_export(bn_r, r, len)); + cx_bn_unlock(); end: - return error; + return error; } -cx_err_t cx_math_mult_no_throw( uint8_t * r, const uint8_t * a, const uint8_t * b, size_t len ) { - cx_bn_t bn_a, bn_b, bn_r; - cx_err_t error; +cx_err_t cx_math_mult_no_throw(uint8_t *r, const uint8_t *a, const uint8_t *b, size_t len) +{ + cx_bn_t bn_a, bn_b, bn_r; + cx_err_t error; - CX_CHECK(cx_bn_lock(len, 0)); - CX_CHECK(cx_bn_alloc(&bn_r, 2*len)); - CX_CHECK(cx_bn_alloc_init(&bn_a, len, a, len)); - CX_CHECK(cx_bn_alloc_init(&bn_b, len, b, len)); - CX_CHECK(cx_bn_mul(bn_r, bn_a, bn_b)); - CX_CHECK(cx_bn_export(bn_r, r, 2*len)); - cx_bn_unlock(); + CX_CHECK(cx_bn_lock(len, 0)); + CX_CHECK(cx_bn_alloc(&bn_r, 2 * len)); + CX_CHECK(cx_bn_alloc_init(&bn_a, len, a, len)); + CX_CHECK(cx_bn_alloc_init(&bn_b, len, b, len)); + CX_CHECK(cx_bn_mul(bn_r, bn_a, bn_b)); + CX_CHECK(cx_bn_export(bn_r, r, 2 * len)); + cx_bn_unlock(); end: - return error; + return error; } -cx_err_t cx_math_addm_no_throw( uint8_t * r, const uint8_t * a, const uint8_t * b, const uint8_t * m, size_t len ) { - cx_bn_t bn_a, bn_b, bn_m, bn_r; - cx_err_t error; - - CX_CHECK(cx_bn_lock(len, 0)); - CX_CHECK(cx_bn_alloc(&bn_r, len)); - CX_CHECK(cx_bn_alloc_init(&bn_a, len, a, len)); - CX_CHECK(cx_bn_alloc_init(&bn_b, len, b, len)); - CX_CHECK(cx_bn_alloc_init(&bn_m, len, m, len)); - CX_CHECK(cx_bn_mod_add(bn_r, bn_a, bn_b, bn_m)); +cx_err_t cx_math_addm_no_throw(uint8_t *r, + const uint8_t *a, + const uint8_t *b, + const uint8_t *m, + size_t len) +{ + cx_bn_t bn_a, bn_b, bn_m, bn_r; + cx_err_t error; + + CX_CHECK(cx_bn_lock(len, 0)); + CX_CHECK(cx_bn_alloc(&bn_r, len)); + CX_CHECK(cx_bn_alloc_init(&bn_a, len, a, len)); + CX_CHECK(cx_bn_alloc_init(&bn_b, len, b, len)); + CX_CHECK(cx_bn_alloc_init(&bn_m, len, m, len)); + CX_CHECK(cx_bn_mod_add(bn_r, bn_a, bn_b, bn_m)); #ifdef ST33K1M5 - cx_bn_set_u32(bn_a, 0); - CX_CHECK(cx_bn_mod_sub(bn_r, bn_r, bn_a, bn_m)); -#endif // ST33K1M5 - CX_CHECK(cx_bn_export(bn_r, r, len)); - cx_bn_unlock(); + cx_bn_set_u32(bn_a, 0); + CX_CHECK(cx_bn_mod_sub(bn_r, bn_r, bn_a, bn_m)); +#endif // ST33K1M5 + CX_CHECK(cx_bn_export(bn_r, r, len)); + cx_bn_unlock(); end: - return error; + return error; } -cx_err_t cx_math_subm_no_throw( uint8_t * r, const uint8_t * a, const uint8_t * b, const uint8_t * m, size_t len ) { - cx_bn_t bn_a, bn_b, bn_m, bn_r; - cx_err_t error; - - CX_CHECK(cx_bn_lock(len, 0)); - CX_CHECK(cx_bn_alloc(&bn_r, len)); - CX_CHECK(cx_bn_alloc_init(&bn_a, len, a, len)); - CX_CHECK(cx_bn_alloc_init(&bn_b, len, b, len)); - CX_CHECK(cx_bn_alloc_init(&bn_m, len, m, len)); - CX_CHECK(cx_bn_mod_sub(bn_r, bn_a, bn_b, bn_m)); - CX_CHECK(cx_bn_export(bn_r, r, len)); - cx_bn_unlock(); +cx_err_t cx_math_subm_no_throw(uint8_t *r, + const uint8_t *a, + const uint8_t *b, + const uint8_t *m, + size_t len) +{ + cx_bn_t bn_a, bn_b, bn_m, bn_r; + cx_err_t error; + + CX_CHECK(cx_bn_lock(len, 0)); + CX_CHECK(cx_bn_alloc(&bn_r, len)); + CX_CHECK(cx_bn_alloc_init(&bn_a, len, a, len)); + CX_CHECK(cx_bn_alloc_init(&bn_b, len, b, len)); + CX_CHECK(cx_bn_alloc_init(&bn_m, len, m, len)); + CX_CHECK(cx_bn_mod_sub(bn_r, bn_a, bn_b, bn_m)); + CX_CHECK(cx_bn_export(bn_r, r, len)); + cx_bn_unlock(); end: - return error; + return error; } -cx_err_t cx_math_multm_no_throw( uint8_t * r, const uint8_t * a, const uint8_t * b, const uint8_t * m, size_t len ) { - cx_bn_t bn_a, bn_b, bn_m, bn_r; - cx_err_t error; - - CX_CHECK(cx_bn_lock(len, 0)); - CX_CHECK(cx_bn_alloc(&bn_r, len)); - CX_CHECK(cx_bn_alloc_init(&bn_a, len, a, len)); - CX_CHECK(cx_bn_alloc_init(&bn_b, len, b, len)); - CX_CHECK(cx_bn_alloc_init(&bn_m, len, m, len)); - CX_CHECK(cx_bn_mod_mul(bn_r, bn_a, bn_b, bn_m)); - CX_CHECK(cx_bn_export(bn_r, r, len)); - cx_bn_unlock(); +cx_err_t cx_math_multm_no_throw(uint8_t *r, + const uint8_t *a, + const uint8_t *b, + const uint8_t *m, + size_t len) +{ + cx_bn_t bn_a, bn_b, bn_m, bn_r; + cx_err_t error; + + CX_CHECK(cx_bn_lock(len, 0)); + CX_CHECK(cx_bn_alloc(&bn_r, len)); + CX_CHECK(cx_bn_alloc_init(&bn_a, len, a, len)); + CX_CHECK(cx_bn_alloc_init(&bn_b, len, b, len)); + CX_CHECK(cx_bn_alloc_init(&bn_m, len, m, len)); + CX_CHECK(cx_bn_mod_mul(bn_r, bn_a, bn_b, bn_m)); + CX_CHECK(cx_bn_export(bn_r, r, len)); + cx_bn_unlock(); end: - return error; + return error; } -cx_err_t cx_math_modm_no_throw( uint8_t * v, size_t len_v, const uint8_t * m, size_t len_m ) { - cx_bn_t bn_v, bn_m, bn_r; - cx_err_t error; +cx_err_t cx_math_modm_no_throw(uint8_t *v, size_t len_v, const uint8_t *m, size_t len_m) +{ + cx_bn_t bn_v, bn_m, bn_r; + cx_err_t error; - CX_CHECK(cx_bn_lock(len_v, 0)); - CX_CHECK(cx_bn_alloc(&bn_r, len_v)); - CX_CHECK(cx_bn_alloc_init(&bn_v, len_v, v, len_v)); - CX_CHECK(cx_bn_alloc_init(&bn_m, len_m, m, len_m)); - CX_CHECK(cx_bn_reduce(bn_r, bn_v, bn_m)); - CX_CHECK(cx_bn_export(bn_r, v, len_v)); - cx_bn_unlock(); + CX_CHECK(cx_bn_lock(len_v, 0)); + CX_CHECK(cx_bn_alloc(&bn_r, len_v)); + CX_CHECK(cx_bn_alloc_init(&bn_v, len_v, v, len_v)); + CX_CHECK(cx_bn_alloc_init(&bn_m, len_m, m, len_m)); + CX_CHECK(cx_bn_reduce(bn_r, bn_v, bn_m)); + CX_CHECK(cx_bn_export(bn_r, v, len_v)); + cx_bn_unlock(); end: - return error; + return error; } -cx_err_t cx_math_powm_no_throw( uint8_t * r, const uint8_t * a, const uint8_t * e, size_t len_e, const uint8_t * m, size_t len ) { - cx_bn_t bn_a, bn_m, bn_r; - cx_err_t error; - - CX_CHECK(cx_bn_lock(len, 0)); - CX_CHECK(cx_bn_alloc_init(&bn_a, len, a, len)); - CX_CHECK(cx_bn_alloc_init(&bn_m, len, m, len)); - CX_CHECK(cx_bn_alloc(&bn_r, len)); - CX_CHECK(cx_bn_mod_pow2(bn_r, bn_a, e, len_e, bn_m)); - CX_CHECK(cx_bn_export(bn_r, r, len)); - cx_bn_unlock(); +cx_err_t cx_math_powm_no_throw(uint8_t *r, + const uint8_t *a, + const uint8_t *e, + size_t len_e, + const uint8_t *m, + size_t len) +{ + cx_bn_t bn_a, bn_m, bn_r; + cx_err_t error; + + CX_CHECK(cx_bn_lock(len, 0)); + CX_CHECK(cx_bn_alloc_init(&bn_a, len, a, len)); + CX_CHECK(cx_bn_alloc_init(&bn_m, len, m, len)); + CX_CHECK(cx_bn_alloc(&bn_r, len)); + CX_CHECK(cx_bn_mod_pow2(bn_r, bn_a, e, len_e, bn_m)); + CX_CHECK(cx_bn_export(bn_r, r, len)); + cx_bn_unlock(); end: - return error; + return error; } -cx_err_t cx_math_invprimem_no_throw( uint8_t * r, const uint8_t * a, const uint8_t * m, size_t len ) { - cx_bn_t bn_a, bn_r, bn_m; - cx_err_t error; +cx_err_t cx_math_invprimem_no_throw(uint8_t *r, const uint8_t *a, const uint8_t *m, size_t len) +{ + cx_bn_t bn_a, bn_r, bn_m; + cx_err_t error; - CX_CHECK(cx_bn_lock(len, 0)); - CX_CHECK(cx_bn_alloc(&bn_r, len)); - CX_CHECK(cx_bn_alloc_init(&bn_a, len, a, len)); - CX_CHECK(cx_bn_alloc_init(&bn_m, len, m, len)); - CX_CHECK(cx_bn_mod_invert_nprime(bn_r, bn_a, bn_m)); - CX_CHECK(cx_bn_export(bn_r, r, len)); - cx_bn_unlock(); + CX_CHECK(cx_bn_lock(len, 0)); + CX_CHECK(cx_bn_alloc(&bn_r, len)); + CX_CHECK(cx_bn_alloc_init(&bn_a, len, a, len)); + CX_CHECK(cx_bn_alloc_init(&bn_m, len, m, len)); + CX_CHECK(cx_bn_mod_invert_nprime(bn_r, bn_a, bn_m)); + CX_CHECK(cx_bn_export(bn_r, r, len)); + cx_bn_unlock(); end: - return error; + return error; } -cx_err_t cx_math_invintm_no_throw( uint8_t * r, uint32_t a, const uint8_t * m, size_t len ) { - cx_bn_t bn_r, bn_m; - cx_err_t error; +cx_err_t cx_math_invintm_no_throw(uint8_t *r, uint32_t a, const uint8_t *m, size_t len) +{ + cx_bn_t bn_r, bn_m; + cx_err_t error; - CX_CHECK(cx_bn_lock(len, 0)); - CX_CHECK(cx_bn_alloc(&bn_r, len)); - CX_CHECK(cx_bn_alloc_init(&bn_m, len, m, len)); - CX_CHECK(cx_bn_mod_u32_invert(bn_r, a, bn_m)); - CX_CHECK(cx_bn_export(bn_r, r, len)); - cx_bn_unlock(); + CX_CHECK(cx_bn_lock(len, 0)); + CX_CHECK(cx_bn_alloc(&bn_r, len)); + CX_CHECK(cx_bn_alloc_init(&bn_m, len, m, len)); + CX_CHECK(cx_bn_mod_u32_invert(bn_r, a, bn_m)); + CX_CHECK(cx_bn_export(bn_r, r, len)); + cx_bn_unlock(); end: - return error; + return error; } -cx_err_t cx_math_is_prime_no_throw( const uint8_t * r, size_t len, bool *prime) { - cx_bn_t bn_r; - cx_err_t error; +cx_err_t cx_math_is_prime_no_throw(const uint8_t *r, size_t len, bool *prime) +{ + cx_bn_t bn_r; + cx_err_t error; - CX_CHECK(cx_bn_lock(len, 0)); - CX_CHECK(cx_bn_alloc_init(&bn_r, len, r, len)); - CX_CHECK(cx_bn_is_prime(bn_r, prime)); - cx_bn_unlock(); + CX_CHECK(cx_bn_lock(len, 0)); + CX_CHECK(cx_bn_alloc_init(&bn_r, len, r, len)); + CX_CHECK(cx_bn_is_prime(bn_r, prime)); + cx_bn_unlock(); end: - return error; + return error; } -cx_err_t cx_math_next_prime_no_throw( uint8_t * r, uint32_t len ) { - cx_bn_t bn_r; - cx_err_t error; +cx_err_t cx_math_next_prime_no_throw(uint8_t *r, uint32_t len) +{ + cx_bn_t bn_r; + cx_err_t error; - CX_CHECK(cx_bn_lock(len, 0)); - CX_CHECK(cx_bn_alloc_init(&bn_r, len, r, len)); - CX_CHECK(cx_bn_next_prime(bn_r)); - CX_CHECK(cx_bn_export(bn_r, r, len)); - cx_bn_unlock(); + CX_CHECK(cx_bn_lock(len, 0)); + CX_CHECK(cx_bn_alloc_init(&bn_r, len, r, len)); + CX_CHECK(cx_bn_next_prime(bn_r)); + CX_CHECK(cx_bn_export(bn_r, r, len)); + cx_bn_unlock(); end: - return error; + return error; } -#endif // HAVE_MATH +#endif // HAVE_MATH diff --git a/lib_cxng/src/cx_math.h b/lib_cxng/src/cx_math.h index 0b1391d35..274fa3935 100644 --- a/lib_cxng/src/cx_math.h +++ b/lib_cxng/src/cx_math.h @@ -1,20 +1,20 @@ /******************************************************************************* -* Ledger Nano S - Secure firmware -* (c) 2022 Ledger -* -* Licensed under the Apache License, Version 2.0 (the "License"); -* you may not use this file except in compliance with the License. -* You may obtain a copy of the License at -* -* http://www.apache.org/licenses/LICENSE-2.0 -* -* Unless required by applicable law or agreed to in writing, software -* distributed under the License is distributed on an "AS IS" BASIS, -* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -* See the License for the specific language governing permissions and -* limitations under the License. -********************************************************************************/ + * Ledger Nano S - Secure firmware + * (c) 2022 Ledger + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + ********************************************************************************/ #ifdef HAVE_MATH @@ -23,6 +23,6 @@ #include "lcx_math.h" -#endif // CX_MATH_H +#endif // CX_MATH_H -#endif // HAVE_MATH +#endif // HAVE_MATH diff --git a/lib_cxng/src/cx_pbkdf2.c b/lib_cxng/src/cx_pbkdf2.c index e4bbd89d2..5fb181629 100644 --- a/lib_cxng/src/cx_pbkdf2.c +++ b/lib_cxng/src/cx_pbkdf2.c @@ -1,20 +1,20 @@ /******************************************************************************* -* Ledger Nano S - Secure firmware -* (c) 2022 Ledger -* -* Licensed under the Apache License, Version 2.0 (the "License"); -* you may not use this file except in compliance with the License. -* You may obtain a copy of the License at -* -* http://www.apache.org/licenses/LICENSE-2.0 -* -* Unless required by applicable law or agreed to in writing, software -* distributed under the License is distributed on an "AS IS" BASIS, -* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -* See the License for the specific language governing permissions and -* limitations under the License. -********************************************************************************/ + * Ledger Nano S - Secure firmware + * (c) 2022 Ledger + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + ********************************************************************************/ #ifdef HAVE_PBKDF2 @@ -32,75 +32,78 @@ cx_err_t cx_pbkdf2_hmac(cx_md_t md_type, const uint8_t *salt, size_t salt_len, uint32_t iterations, - uint8_t * key, - size_t key_len) { - cx_hmac_t *hmac_ctx = &G_cx.pbkdf2.hmac_ctx; - uint8_t counter[4]; - uint8_t * work = G_cx.pbkdf2.work; - size_t work_size; - uint8_t * md1 = G_cx.pbkdf2.md1; - size_t copy_len; - size_t digest_size; - - if (password == NULL || salt == NULL || key == NULL) { - return CX_INVALID_PARAMETER; - } - - const cx_hash_info_t *info = cx_hash_get_info(md_type); - digest_size = info->output_size; - - memset(counter, 0, sizeof(counter)); - counter[sizeof(counter) - 1] = 1; - - while (key_len) { - cx_hmac_init(hmac_ctx, md_type, password, password_len); - cx_hmac_update(hmac_ctx, salt, salt_len); - cx_hmac_update(hmac_ctx, counter, 4); - - work_size = digest_size; - cx_hmac_final(hmac_ctx, work, &work_size); - - memcpy(md1, work, digest_size); - for (uint32_t i = 1; i < iterations; i++) { - cx_hmac_init(hmac_ctx, md_type, password, password_len); - cx_hmac_update(hmac_ctx, md1, digest_size); - work_size = digest_size; - cx_hmac_final(hmac_ctx, md1, &work_size); - - for (unsigned int j = 0; j < digest_size; j++) { - work[j] ^= md1[j]; - } + uint8_t *key, + size_t key_len) +{ + cx_hmac_t *hmac_ctx = &G_cx.pbkdf2.hmac_ctx; + uint8_t counter[4]; + uint8_t *work = G_cx.pbkdf2.work; + size_t work_size; + uint8_t *md1 = G_cx.pbkdf2.md1; + size_t copy_len; + size_t digest_size; + + if (password == NULL || salt == NULL || key == NULL) { + return CX_INVALID_PARAMETER; } - if (key_len < digest_size) { - copy_len = key_len; - } else { - copy_len = digest_size; + const cx_hash_info_t *info = cx_hash_get_info(md_type); + digest_size = info->output_size; + + memset(counter, 0, sizeof(counter)); + counter[sizeof(counter) - 1] = 1; + + while (key_len) { + cx_hmac_init(hmac_ctx, md_type, password, password_len); + cx_hmac_update(hmac_ctx, salt, salt_len); + cx_hmac_update(hmac_ctx, counter, 4); + + work_size = digest_size; + cx_hmac_final(hmac_ctx, work, &work_size); + + memcpy(md1, work, digest_size); + for (uint32_t i = 1; i < iterations; i++) { + cx_hmac_init(hmac_ctx, md_type, password, password_len); + cx_hmac_update(hmac_ctx, md1, digest_size); + work_size = digest_size; + cx_hmac_final(hmac_ctx, md1, &work_size); + + for (unsigned int j = 0; j < digest_size; j++) { + work[j] ^= md1[j]; + } + } + + if (key_len < digest_size) { + copy_len = key_len; + } + else { + copy_len = digest_size; + } + memcpy(key, work, copy_len); + key += copy_len; + key_len -= copy_len; + + // Increment counter + for (int i = 3; i >= 0; i--) { + if (++counter[i] != 0) { + break; + } + } } - memcpy(key, work, copy_len); - key += copy_len; - key_len -= copy_len; - - // Increment counter - for (int i = 3; i >= 0; i--) { - if (++counter[i] != 0) { - break; - } - } - } - return CX_OK; + return CX_OK; } - -cx_err_t cx_pbkdf2_no_throw(cx_md_t md_type, - const uint8_t *password, - size_t password_len, - uint8_t * salt, - size_t salt_len, - uint32_t iterations, - uint8_t * out, - size_t out_len) { - return cx_pbkdf2_hmac(md_type, password, password_len, salt, salt_len, iterations, out, out_len); +cx_err_t cx_pbkdf2_no_throw(cx_md_t md_type, + const uint8_t *password, + size_t password_len, + uint8_t *salt, + size_t salt_len, + uint32_t iterations, + uint8_t *out, + size_t out_len) +{ + return cx_pbkdf2_hmac( + md_type, password, password_len, salt, salt_len, iterations, out, out_len); } -#endif // HAVE_PBKDF2 +#endif // HAVE_PBKDF2 diff --git a/lib_cxng/src/cx_pbkdf2.h b/lib_cxng/src/cx_pbkdf2.h index ca5c1f63f..183e1bbc7 100644 --- a/lib_cxng/src/cx_pbkdf2.h +++ b/lib_cxng/src/cx_pbkdf2.h @@ -1,20 +1,20 @@ /******************************************************************************* -* Ledger Nano S - Secure firmware -* (c) 2022 Ledger -* -* Licensed under the Apache License, Version 2.0 (the "License"); -* you may not use this file except in compliance with the License. -* You may obtain a copy of the License at -* -* http://www.apache.org/licenses/LICENSE-2.0 -* -* Unless required by applicable law or agreed to in writing, software -* distributed under the License is distributed on an "AS IS" BASIS, -* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -* See the License for the specific language governing permissions and -* limitations under the License. -********************************************************************************/ + * Ledger Nano S - Secure firmware + * (c) 2022 Ledger + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + ********************************************************************************/ #ifdef HAVE_PBKDF2 @@ -26,31 +26,31 @@ #include #include -#define PBKDF2_BUFFER_LENGTH 64 +#define PBKDF2_BUFFER_LENGTH 64 /* ========= PBKDF2 ========= */ struct cx_pbkdf2_s { - // salt buffer used to initialize each pbkdf2 turn. - uint8_t salt[384]; - uint8_t sha512out[64]; // avoid stack usage in derive_and_set_seed + // salt buffer used to initialize each pbkdf2 turn. + uint8_t salt[384]; + uint8_t sha512out[64]; // avoid stack usage in derive_and_set_seed - uint8_t work[PBKDF2_BUFFER_LENGTH]; - uint8_t md1[PBKDF2_BUFFER_LENGTH]; - union { - #if !defined(HAVE_SHA512) && !defined(HAVE_SHA384) && !defined(HAVE_SHA256) && !defined(HAVE_SHA224) - #error No hmac defined for pbkdf2 support - #endif + uint8_t work[PBKDF2_BUFFER_LENGTH]; + uint8_t md1[PBKDF2_BUFFER_LENGTH]; + union { +#if !defined(HAVE_SHA512) && !defined(HAVE_SHA384) && !defined(HAVE_SHA256) && !defined(HAVE_SHA224) +#error No hmac defined for pbkdf2 support +#endif - cx_hmac_t hmac_ctx; + cx_hmac_t hmac_ctx; - #if defined(HAVE_HMAC) && (defined(HAVE_SHA512) || defined(HAVE_SHA384)) - cx_hmac_sha512_t hmac_sha512; - #endif +#if defined(HAVE_HMAC) && (defined(HAVE_SHA512) || defined(HAVE_SHA384)) + cx_hmac_sha512_t hmac_sha512; +#endif - #if defined(HAVE_HMAC) && (defined(HAVE_SHA256) || defined(HAVE_SHA224)) - cx_hmac_sha256_t hmac_sha256; - #endif - }; +#if defined(HAVE_HMAC) && (defined(HAVE_SHA256) || defined(HAVE_SHA224)) + cx_hmac_sha256_t hmac_sha256; +#endif + }; }; typedef struct cx_pbkdf2_s cx_pbkdf2_t; @@ -60,8 +60,8 @@ cx_err_t cx_pbkdf2_hmac(cx_md_t md_type, const uint8_t *salt, size_t salt_len, uint32_t iterations, - uint8_t * key, + uint8_t *key, size_t key_len); -#endif // CX_PBKDF2_H -#endif // HAVE_PBKDF2 +#endif // CX_PBKDF2_H +#endif // HAVE_PBKDF2 diff --git a/lib_cxng/src/cx_pkcs1.c b/lib_cxng/src/cx_pkcs1.c index 500b09b05..f0bf8883f 100644 --- a/lib_cxng/src/cx_pkcs1.c +++ b/lib_cxng/src/cx_pkcs1.c @@ -1,20 +1,20 @@ /******************************************************************************* -* Ledger Nano S - Secure firmware -* (c) 2022 Ledger -* -* Licensed under the Apache License, Version 2.0 (the "License"); -* you may not use this file except in compliance with the License. -* You may obtain a copy of the License at -* -* http://www.apache.org/licenses/LICENSE-2.0 -* -* Unless required by applicable law or agreed to in writing, software -* distributed under the License is distributed on an "AS IS" BASIS, -* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -* See the License for the specific language governing permissions and -* limitations under the License. -********************************************************************************/ + * Ledger Nano S - Secure firmware + * (c) 2022 Ledger + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + ********************************************************************************/ #ifdef HAVE_RSA @@ -33,6 +33,7 @@ /* */ /* ----------------------------------------------------------------------- */ +// clang-format off #if defined(HAVE_SHA224) /* sha224 OID */ const uint8_t C_cx_oid_sha224[CX_OID_SHA224_LENGTH] = {0x30, 0x2d, 0x30, 0x0d, 0x06, 0x09, 0x60, 0x86, 0x48, 0x01, @@ -68,90 +69,93 @@ const uint8_t C_cx_oid_sha3_512[CX_OID_SHA3_512_LENGTH] = {0x30, 0x51, 0x30, 0x0d, 0x06, 0x09, 0x60, 0x86, 0x48, 0x01, 0x65, 0x03, 0x04, 0x02, 0x0a, 0x05, 0x00, 0x04, 0x40}; #endif // HAVE_SHA3 +// clang-format on -size_t cx_pkcs1_get_hash_len(cx_md_t hID) { - switch (hID) { +size_t cx_pkcs1_get_hash_len(cx_md_t hID) +{ + switch (hID) { #if defined(HAVE_SHA224) - case CX_SHA224: - return 224/8; -#endif // HAVE_SHA224 + case CX_SHA224: + return 224 / 8; +#endif // HAVE_SHA224 #if defined(HAVE_SHA256) - case CX_SHA256: - return 256/8; -#endif // HAVE_SHA256 + case CX_SHA256: + return 256 / 8; +#endif // HAVE_SHA256 #if defined(HAVE_SHA384) - case CX_SHA384: - return 384/8; -#endif // HAVE_SHA384 + case CX_SHA384: + return 384 / 8; +#endif // HAVE_SHA384 #if defined(HAVE_SHA512) - case CX_SHA512: - return 512/8; -#endif // HAVE_SHA512 + case CX_SHA512: + return 512 / 8; +#endif // HAVE_SHA512 #if defined(HAVE_SHA3) - case CX_SHA3_256: - return 256/8; + case CX_SHA3_256: + return 256 / 8; - case CX_SHA3_512: - return 512/8; -#endif // HAVE_SHA3 + case CX_SHA3_512: + return 512 / 8; +#endif // HAVE_SHA3 - default: - break; - } - return 0; + default: + break; + } + return 0; } -static const uint8_t *cx_pkcs1_get_hash_oid(cx_md_t hID, size_t *len) { - switch (hID) { +static const uint8_t *cx_pkcs1_get_hash_oid(cx_md_t hID, size_t *len) +{ + switch (hID) { #if defined(HAVE_SHA224) - case CX_SHA224: - *len = sizeof(C_cx_oid_sha224); - return C_cx_oid_sha224; -#endif // HAVE_SHA224 + case CX_SHA224: + *len = sizeof(C_cx_oid_sha224); + return C_cx_oid_sha224; +#endif // HAVE_SHA224 #if defined(HAVE_SHA256) - case CX_SHA256: - *len = sizeof(C_cx_oid_sha256); - return C_cx_oid_sha256; -#endif // HAVE_SHA256 + case CX_SHA256: + *len = sizeof(C_cx_oid_sha256); + return C_cx_oid_sha256; +#endif // HAVE_SHA256 #if defined(HAVE_SHA384) - case CX_SHA384: - *len = sizeof(C_cx_oid_sha384); - return C_cx_oid_sha384; -#endif // HAVE_SHA384 + case CX_SHA384: + *len = sizeof(C_cx_oid_sha384); + return C_cx_oid_sha384; +#endif // HAVE_SHA384 #if defined(HAVE_SHA512) - case CX_SHA512: - *len = sizeof(C_cx_oid_sha512); - return C_cx_oid_sha512; -#endif // HAVE_SHA512 + case CX_SHA512: + *len = sizeof(C_cx_oid_sha512); + return C_cx_oid_sha512; +#endif // HAVE_SHA512 #if defined(HAVE_SHA3) - case CX_SHA3_256: - *len = sizeof(C_cx_oid_sha3_256); - return C_cx_oid_sha3_256; + case CX_SHA3_256: + *len = sizeof(C_cx_oid_sha3_256); + return C_cx_oid_sha3_256; - case CX_SHA3_512: - *len = sizeof(C_cx_oid_sha3_512); - return C_cx_oid_sha3_512; -#endif // HAVE_SHA3 + case CX_SHA3_512: + *len = sizeof(C_cx_oid_sha3_512); + return C_cx_oid_sha3_512; +#endif // HAVE_SHA3 - default: - break; - } - *len = 0; - return NULL; + default: + break; + } + *len = 0; + return NULL; } #ifdef _CX_PKCS1_CONST_SEED_SALT -static const uint8_t C_cx_pkcs_salt[] = {'T', 'h', 'e', 'S', 'a', 'l', 't', ' ', 'T', 'h', 'e', - 'S', 'a', 'l', 't', ' ', 'T', 'h', 'e', 'S', 'a', 'l', - 't', ' ', 'T', 'h', 'e', 'S', 'a', 'l', 't', ' '}; +static const uint8_t C_cx_pkcs_salt[] + = {'T', 'h', 'e', 'S', 'a', 'l', 't', ' ', 'T', 'h', 'e', 'S', 'a', 'l', 't', ' ', + 'T', 'h', 'e', 'S', 'a', 'l', 't', ' ', 'T', 'h', 'e', 'S', 'a', 'l', 't', ' '}; #endif static const uint8_t C_cx_pss_zeros[] = {0, 0, 0, 0, 0, 0, 0, 0}; @@ -159,107 +163,102 @@ static const uint8_t C_cx_pss_zeros[] = {0, 0, 0, 0, 0, 0, 0, 0}; // We only support the empty string label, defined as default. // The following arrays are the corresponding hash applied to this empty string label. #if defined(HAVE_SHA224) -static const uint8_t C_cx_oeap_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}; -#endif // HAVE_SHA224 +static const uint8_t C_cx_oeap_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}; +#endif // HAVE_SHA224 #if defined(HAVE_SHA256) static const uint8_t C_cx_oeap_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, + 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, }; -#endif // HAVE_SHA256 +#endif // HAVE_SHA256 #if defined(HAVE_SHA384) static const uint8_t C_cx_oeap_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}; -#endif // HAVE_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}; +#endif // HAVE_SHA384 #if defined(HAVE_SHA512) static const uint8_t C_cx_oeap_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}; -#endif // HAVE_SHA512 - -static const uint8_t *cx_pkcs1_get_hash_oeap(cx_md_t hID, size_t *len) { - switch (hID) { + 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}; +#endif // HAVE_SHA512 + +static const uint8_t *cx_pkcs1_get_hash_oeap(cx_md_t hID, size_t *len) +{ + switch (hID) { #if defined(HAVE_SHA224) - case CX_SHA224: - *len = sizeof(C_cx_oeap_sha224_); - return C_cx_oeap_sha224_; -#endif // HAVE_SHA224 + case CX_SHA224: + *len = sizeof(C_cx_oeap_sha224_); + return C_cx_oeap_sha224_; +#endif // HAVE_SHA224 #if defined(HAVE_SHA256) - case CX_SHA256: - *len = sizeof(C_cx_oeap_sha256_); - return C_cx_oeap_sha256_; -#endif // HAVE_SHA256 + case CX_SHA256: + *len = sizeof(C_cx_oeap_sha256_); + return C_cx_oeap_sha256_; +#endif // HAVE_SHA256 #if defined(HAVE_SHA384) - case CX_SHA384: - *len = sizeof(C_cx_oeap_sha384_); - return C_cx_oeap_sha384_; -#endif // HAVE_SHA384 + case CX_SHA384: + *len = sizeof(C_cx_oeap_sha384_); + return C_cx_oeap_sha384_; +#endif // HAVE_SHA384 #if defined(HAVE_SHA512) - case CX_SHA512: - *len = sizeof(C_cx_oeap_sha512_); - return C_cx_oeap_sha512_; -#endif // HAVE_SHA512 + case CX_SHA512: + *len = sizeof(C_cx_oeap_sha512_); + return C_cx_oeap_sha512_; +#endif // HAVE_SHA512 - default: - break; - } - *len = 0; - return NULL; + default: + break; + } + *len = 0; + return NULL; } -static cx_err_t cx_pkcs1_MGF1(cx_md_t hID, uint8_t *seed, size_t seed_len, uint8_t *out, size_t out_len) { - size_t hLen; - size_t round_len; - uint8_t counter[4] = {0}; - cx_hash_t *hash_ctx = &G_cx.pkcs1.hash_ctx.hash; - - if (hID != CX_SHA224 && hID != CX_SHA256 && hID != CX_SHA384 && hID != CX_SHA512 - && hID != CX_SHA3_256 && hID != CX_SHA3_512) { - return CX_INVALID_PARAMETER; - } - hLen = cx_pkcs1_get_hash_len(hID); - - while (out_len) { - round_len = (out_len < hLen) ? out_len : hLen; - - cx_hash_init_ex(hash_ctx, hID, hLen); - cx_hash_update(hash_ctx, seed, seed_len); - cx_hash_update(hash_ctx, counter, 4); - cx_hash_final(hash_ctx, G_cx.pkcs1.digest); - - memcpy(out, G_cx.pkcs1.digest, round_len); - out_len -= round_len; - out += round_len; - counter[3]++; - if (counter[3] == 0) { - counter[2]++; +static cx_err_t cx_pkcs1_MGF1(cx_md_t hID, + uint8_t *seed, + size_t seed_len, + uint8_t *out, + size_t out_len) +{ + size_t hLen; + size_t round_len; + uint8_t counter[4] = {0}; + cx_hash_t *hash_ctx = &G_cx.pkcs1.hash_ctx.hash; + + if (hID != CX_SHA224 && hID != CX_SHA256 && hID != CX_SHA384 && hID != CX_SHA512 + && hID != CX_SHA3_256 && hID != CX_SHA3_512) { + return CX_INVALID_PARAMETER; + } + hLen = cx_pkcs1_get_hash_len(hID); + + while (out_len) { + round_len = (out_len < hLen) ? out_len : hLen; + + cx_hash_init_ex(hash_ctx, hID, hLen); + cx_hash_update(hash_ctx, seed, seed_len); + cx_hash_update(hash_ctx, counter, 4); + cx_hash_final(hash_ctx, G_cx.pkcs1.digest); + + memcpy(out, G_cx.pkcs1.digest, round_len); + out_len -= round_len; + out += round_len; + counter[3]++; + if (counter[3] == 0) { + counter[2]++; + } } - } - return CX_OK; + return CX_OK; } /* ----------------------------------------------------------------------- */ @@ -269,29 +268,34 @@ static cx_err_t cx_pkcs1_MGF1(cx_md_t hID, uint8_t *seed, size_t seed_len, uint8 /* * message: at ptr+size-msg_size */ -cx_err_t cx_pkcs1_emsa_v1o5_encode(cx_md_t hID, uint8_t *em, size_t emLen, const uint8_t *mHash, size_t mHashLen) { - size_t PSLen; - size_t oid_len; - const uint8_t *oid; - - oid = cx_pkcs1_get_hash_oid(hID, &oid_len); - if (oid == NULL) { - return CX_INVALID_PARAMETER; - } - - if ((3 + oid_len + mHashLen) >= emLen) { - return CX_INVALID_PARAMETER; - } - PSLen = emLen - (3 + oid_len + mHashLen); - - memcpy(em + 2 + PSLen + 1 + oid_len, mHash, mHashLen); - memcpy(em + 2 + PSLen + 1, oid, oid_len); - em[0] = 0; - em[1] = 1; - memset(em + 2, 0xFF, PSLen); - em[2 + PSLen] = 0; - - return CX_OK; +cx_err_t cx_pkcs1_emsa_v1o5_encode(cx_md_t hID, + uint8_t *em, + size_t emLen, + const uint8_t *mHash, + size_t mHashLen) +{ + size_t PSLen; + size_t oid_len; + const uint8_t *oid; + + oid = cx_pkcs1_get_hash_oid(hID, &oid_len); + if (oid == NULL) { + return CX_INVALID_PARAMETER; + } + + if ((3 + oid_len + mHashLen) >= emLen) { + return CX_INVALID_PARAMETER; + } + PSLen = emLen - (3 + oid_len + mHashLen); + + memcpy(em + 2 + PSLen + 1 + oid_len, mHash, mHashLen); + memcpy(em + 2 + PSLen + 1, oid, oid_len); + em[0] = 0; + em[1] = 1; + memset(em + 2, 0xFF, PSLen); + em[2 + PSLen] = 0; + + return CX_OK; } /** out @@ -299,39 +303,45 @@ cx_err_t cx_pkcs1_emsa_v1o5_encode(cx_md_t hID, uint8_t *em, size_t emLen, const * return : size unpadded message, -1 else * */ -bool cx_pkcs1_emsa_v1o5_verify(cx_md_t hID, uint8_t *em, size_t emLen, const uint8_t *mHash, size_t mHashLen) { - size_t PSLen; - size_t i; - size_t oid_len; - const uint8_t *oid; - - oid = cx_pkcs1_get_hash_oid(hID, &oid_len); - if (oid == NULL) { - return false; - } - - if ((3 + oid_len + mHashLen) >= emLen) { - return false; - } - PSLen = emLen - (3 + oid_len + mHashLen); - - // -> check 00 01 ... 00 - if ((em[0]) || (em[1] != 1) || (em[2 + PSLen] != 0)) { - return 0; - } - // -> check .. .. FFFFFF .. - for (i = 2 + PSLen - 1; i >= 2; i--) { - if (em[i] != 0xFF) { - return false; - } - } - // check OID / hash - if (memcmp(em + 2 + PSLen + 1, oid, oid_len) != 0 || memcmp(em + 2 + PSLen + 1 + oid_len, mHash, mHashLen) != 0) { - return false; - } - - // OKAY - return true; +bool cx_pkcs1_emsa_v1o5_verify(cx_md_t hID, + uint8_t *em, + size_t emLen, + const uint8_t *mHash, + size_t mHashLen) +{ + size_t PSLen; + size_t i; + size_t oid_len; + const uint8_t *oid; + + oid = cx_pkcs1_get_hash_oid(hID, &oid_len); + if (oid == NULL) { + return false; + } + + if ((3 + oid_len + mHashLen) >= emLen) { + return false; + } + PSLen = emLen - (3 + oid_len + mHashLen); + + // -> check 00 01 ... 00 + if ((em[0]) || (em[1] != 1) || (em[2 + PSLen] != 0)) { + return 0; + } + // -> check .. .. FFFFFF .. + for (i = 2 + PSLen - 1; i >= 2; i--) { + if (em[i] != 0xFF) { + return false; + } + } + // check OID / hash + if (memcmp(em + 2 + PSLen + 1, oid, oid_len) != 0 + || memcmp(em + 2 + PSLen + 1 + oid_len, mHash, mHashLen) != 0) { + return false; + } + + // OKAY + return true; } /* ----------------------------------------------------------------------- */ @@ -339,285 +349,321 @@ bool cx_pkcs1_emsa_v1o5_verify(cx_md_t hID, uint8_t *em, size_t emLen, const uin /* ----------------------------------------------------------------------- */ static uint8_t const CX_PSS_MASK[] = {0, 0x7F, 0x3F, 0x1F, 0xF, 0x7, 0x3, 0x1}; -cx_err_t cx_pkcs1_emsa_pss_encode_with_salt_len(cx_md_t hID, uint8_t *em, size_t emBits, const uint8_t *mHash, size_t mHashLen, size_t mSaltLen, size_t *size) { - uint8_t salt[64]; - size_t hLen; - size_t mDBlen; - size_t PSLen; - size_t emLen; - cx_hash_t *hash_ctx = &G_cx.pkcs1.hash_ctx.hash; - cx_err_t error; - - if (hID != CX_SHA224 && hID != CX_SHA256 && hID != CX_SHA384 && hID != CX_SHA512) { - return CX_INVALID_PARAMETER; - } +cx_err_t cx_pkcs1_emsa_pss_encode_with_salt_len(cx_md_t hID, + uint8_t *em, + size_t emBits, + const uint8_t *mHash, + size_t mHashLen, + size_t mSaltLen, + size_t *size) +{ + uint8_t salt[64]; + size_t hLen; + size_t mDBlen; + size_t PSLen; + size_t emLen; + cx_hash_t *hash_ctx = &G_cx.pkcs1.hash_ctx.hash; + cx_err_t error; + + if (hID != CX_SHA224 && hID != CX_SHA256 && hID != CX_SHA384 && hID != CX_SHA512) { + return CX_INVALID_PARAMETER; + } - hLen = cx_pkcs1_get_hash_len(hID); - emLen = (emBits + 7) / 8; + hLen = cx_pkcs1_get_hash_len(hID); + emLen = (emBits + 7) / 8; - if ((1 + hLen) >= emLen) { - return CX_INVALID_PARAMETER; - } - mDBlen = emLen - (1 + hLen); + if ((1 + hLen) >= emLen) { + return CX_INVALID_PARAMETER; + } + mDBlen = emLen - (1 + hLen); - if ((hLen + mSaltLen + 2) >= emLen) { - return CX_INVALID_PARAMETER; - } - PSLen = emLen - (mSaltLen + hLen + 2); + if ((hLen + mSaltLen + 2) >= emLen) { + return CX_INVALID_PARAMETER; + } + PSLen = emLen - (mSaltLen + hLen + 2); #ifndef _CX_PKCS1_CONST_SEED_SALT - cx_rng_no_throw(salt, mSaltLen); + cx_rng_no_throw(salt, mSaltLen); #endif - cx_hash_init_ex(hash_ctx, hID, hLen); - cx_hash_update(hash_ctx, C_cx_pss_zeros, 8); - cx_hash_update(hash_ctx, mHash, mHashLen); - cx_hash_update(hash_ctx, salt, mSaltLen); - cx_hash_final(hash_ctx, em + mDBlen); - - em[emLen - 1] = 0xbc; - CX_CHECK(cx_pkcs1_MGF1(hID, em + mDBlen, hLen, em, mDBlen)); - em[PSLen] ^= 1; - cx_memxor(em + PSLen + 1, salt, mSaltLen); - em[0] &= CX_PSS_MASK[8 * emLen - emBits]; - *size = emLen; - explicit_bzero(&G_cx.pkcs1, sizeof(cx_pkcs1_t)); - - end: - return error; + cx_hash_init_ex(hash_ctx, hID, hLen); + cx_hash_update(hash_ctx, C_cx_pss_zeros, 8); + cx_hash_update(hash_ctx, mHash, mHashLen); + cx_hash_update(hash_ctx, salt, mSaltLen); + cx_hash_final(hash_ctx, em + mDBlen); + + em[emLen - 1] = 0xbc; + CX_CHECK(cx_pkcs1_MGF1(hID, em + mDBlen, hLen, em, mDBlen)); + em[PSLen] ^= 1; + cx_memxor(em + PSLen + 1, salt, mSaltLen); + em[0] &= CX_PSS_MASK[8 * emLen - emBits]; + *size = emLen; + explicit_bzero(&G_cx.pkcs1, sizeof(cx_pkcs1_t)); + +end: + return error; } -cx_err_t cx_pkcs1_emsa_pss_encode(cx_md_t hID, uint8_t *em, size_t emBits, const uint8_t *mHash, size_t mHashLen, size_t *size) { - size_t hLen = cx_pkcs1_get_hash_len(hID); - return cx_pkcs1_emsa_pss_encode_with_salt_len(hID, em, emBits, mHash, mHashLen, hLen, size); +cx_err_t cx_pkcs1_emsa_pss_encode(cx_md_t hID, + uint8_t *em, + size_t emBits, + const uint8_t *mHash, + size_t mHashLen, + size_t *size) +{ + size_t hLen = cx_pkcs1_get_hash_len(hID); + return cx_pkcs1_emsa_pss_encode_with_salt_len(hID, em, emBits, mHash, mHashLen, hLen, size); } -bool cx_pkcs1_emsa_pss_verify_with_salt_len(cx_md_t hID, uint8_t *em, size_t emBits, const uint8_t *mHash, size_t mHashLen, size_t mSaltLen) { - size_t mDBlen; - size_t PSLen; - size_t i; - size_t emLen; - size_t hLen; - cx_hash_t *hash_ctx = &G_cx.pkcs1.hash_ctx.hash; - - if (hID != CX_SHA224 && hID != CX_SHA256 && hID != CX_SHA384 && hID != CX_SHA512) { - return false; - } - - hLen = cx_pkcs1_get_hash_len(hID); - emLen = (emBits + 7) / 8; - - if ((1 + hLen) >= emLen) { - return false; - } - mDBlen = emLen - (1 + hLen); - - if ((mSaltLen + hLen + 2) >= emLen) { - return false; - } - PSLen = emLen - (mSaltLen + hLen + 2); - - if (em[emLen - 1] != 0xbc) { - return false; - } - if (em[0] & ~CX_PSS_MASK[8 * emLen - emBits]) { - return false; - } - if (cx_pkcs1_MGF1(hID, em + mDBlen, hLen, G_cx.pkcs1.MGF1, mDBlen) != CX_OK) { - return false; - } - cx_memxor(em, G_cx.pkcs1.MGF1, mDBlen); - em[0] &= CX_PSS_MASK[8 * emLen - emBits]; - for (i = 0; i < PSLen; i++) { - if (em[i] != 0) { - return false; - } - } - if (em[PSLen] != 0x01) { - return false; - } - - cx_hash_init_ex(hash_ctx, hID, hLen); - cx_hash_update(hash_ctx, C_cx_pss_zeros, 8); - cx_hash_update(hash_ctx, mHash, mHashLen); - cx_hash_update(hash_ctx, em + PSLen + 1, mSaltLen); - cx_hash_final(hash_ctx, G_cx.pkcs1.digest); - - return memcmp(G_cx.pkcs1.digest, em + mDBlen, hLen) == 0; +bool cx_pkcs1_emsa_pss_verify_with_salt_len(cx_md_t hID, + uint8_t *em, + size_t emBits, + const uint8_t *mHash, + size_t mHashLen, + size_t mSaltLen) +{ + size_t mDBlen; + size_t PSLen; + size_t i; + size_t emLen; + size_t hLen; + cx_hash_t *hash_ctx = &G_cx.pkcs1.hash_ctx.hash; + + if (hID != CX_SHA224 && hID != CX_SHA256 && hID != CX_SHA384 && hID != CX_SHA512) { + return false; + } + + hLen = cx_pkcs1_get_hash_len(hID); + emLen = (emBits + 7) / 8; + + if ((1 + hLen) >= emLen) { + return false; + } + mDBlen = emLen - (1 + hLen); + + if ((mSaltLen + hLen + 2) >= emLen) { + return false; + } + PSLen = emLen - (mSaltLen + hLen + 2); + + if (em[emLen - 1] != 0xbc) { + return false; + } + if (em[0] & ~CX_PSS_MASK[8 * emLen - emBits]) { + return false; + } + if (cx_pkcs1_MGF1(hID, em + mDBlen, hLen, G_cx.pkcs1.MGF1, mDBlen) != CX_OK) { + return false; + } + cx_memxor(em, G_cx.pkcs1.MGF1, mDBlen); + em[0] &= CX_PSS_MASK[8 * emLen - emBits]; + for (i = 0; i < PSLen; i++) { + if (em[i] != 0) { + return false; + } + } + if (em[PSLen] != 0x01) { + return false; + } + + cx_hash_init_ex(hash_ctx, hID, hLen); + cx_hash_update(hash_ctx, C_cx_pss_zeros, 8); + cx_hash_update(hash_ctx, mHash, mHashLen); + cx_hash_update(hash_ctx, em + PSLen + 1, mSaltLen); + cx_hash_final(hash_ctx, G_cx.pkcs1.digest); + + return memcmp(G_cx.pkcs1.digest, em + mDBlen, hLen) == 0; } -bool cx_pkcs1_emsa_pss_verify(cx_md_t hID, uint8_t *em, size_t emBits, const uint8_t *mHash, size_t mHashLen) { - // By default and by convention, the salt length is the hash length. - // In order to verify a RSA PSS signature with a variable salt length, - // the 'cx_pkcs1_emsa_pss_verify_with_salt_len' function must be - // used directly. - size_t hLen = cx_pkcs1_get_hash_len(hID); - return cx_pkcs1_emsa_pss_verify_with_salt_len(hID, em, emBits, mHash, mHashLen, hLen); +bool cx_pkcs1_emsa_pss_verify(cx_md_t hID, + uint8_t *em, + size_t emBits, + const uint8_t *mHash, + size_t mHashLen) +{ + // By default and by convention, the salt length is the hash length. + // In order to verify a RSA PSS signature with a variable salt length, + // the 'cx_pkcs1_emsa_pss_verify_with_salt_len' function must be + // used directly. + size_t hLen = cx_pkcs1_get_hash_len(hID); + return cx_pkcs1_emsa_pss_verify_with_salt_len(hID, em, emBits, mHash, mHashLen, hLen); } /* ----------------------------------------------------------------------- */ /* EME: pkcs1 V1.5 */ /* ----------------------------------------------------------------------- */ -cx_err_t cx_pkcs1_eme_v1o5_encode(cx_md_t hID, uint8_t *em, size_t emLen, const uint8_t *m, size_t mLen) { - size_t PSLen; - size_t offset; - (void)hID; - - if ((3 + mLen) >= emLen) { - return CX_INVALID_PARAMETER; - } - PSLen = emLen - (3 + mLen); - - memcpy(em + 2 + PSLen + 1, m, mLen); - em[0] = 0; - em[1] = 2; - cx_rng_no_throw(em + 2, PSLen); - for (offset = 2 + PSLen - 1; offset >= 2; offset--) { - if (em[offset] == 0) { - em[offset] = 0x24; - } - } - em[2 + PSLen] = 0; - return CX_OK; +cx_err_t cx_pkcs1_eme_v1o5_encode(cx_md_t hID, + uint8_t *em, + size_t emLen, + const uint8_t *m, + size_t mLen) +{ + size_t PSLen; + size_t offset; + (void) hID; + + if ((3 + mLen) >= emLen) { + return CX_INVALID_PARAMETER; + } + PSLen = emLen - (3 + mLen); + + memcpy(em + 2 + PSLen + 1, m, mLen); + em[0] = 0; + em[1] = 2; + cx_rng_no_throw(em + 2, PSLen); + for (offset = 2 + PSLen - 1; offset >= 2; offset--) { + if (em[offset] == 0) { + em[offset] = 0x24; + } + } + em[2 + PSLen] = 0; + return CX_OK; } -size_t cx_pkcs1_eme_v1o5_decode(cx_md_t hID, uint8_t *em, size_t emLen, uint8_t *m, size_t mLen) { - size_t offset; - (void)hID; - // -> check 00 02 ... 00 - if ((em[0]) || (em[1] != 2)) { - return -1; - } - // -> check .. .. FFFFFF .. - offset = 2; - while (offset < emLen) { - if (em[offset] == 0) { - break; +size_t cx_pkcs1_eme_v1o5_decode(cx_md_t hID, uint8_t *em, size_t emLen, uint8_t *m, size_t mLen) +{ + size_t offset; + (void) hID; + // -> check 00 02 ... 00 + if ((em[0]) || (em[1] != 2)) { + return -1; + } + // -> check .. .. FFFFFF .. + offset = 2; + while (offset < emLen) { + if (em[offset] == 0) { + break; + } + offset++; + } + if (offset == emLen) { + return -1; } offset++; - } - if (offset == emLen) { - return -1; - } - offset++; - // copy M - if (mLen < emLen - offset) { - return -1; - } - mLen = emLen - offset; - memmove(m, em + offset, mLen); - return mLen; + // copy M + if (mLen < emLen - offset) { + return -1; + } + mLen = emLen - offset; + memmove(m, em + offset, mLen); + return mLen; } /* ----------------------------------------------------------------------- */ /* EME: pkcs1 OAEP */ /* ----------------------------------------------------------------------- */ -cx_err_t cx_pkcs1_eme_oaep_encode(cx_md_t hID, uint8_t *em, size_t emLen, const uint8_t *m, size_t mLen) { - size_t mDBlen; - size_t psLen; - size_t offset; - uint8_t seed[64]; - size_t hLen; - const uint8_t *lHash; - size_t lHashLen; - cx_err_t error; - - hLen = cx_pkcs1_get_hash_len(hID); - lHash = cx_pkcs1_get_hash_oeap(hID, &lHashLen); - if (hLen == 0 || lHash == NULL) { - return CX_INVALID_PARAMETER; - } - - if ((hLen + 1) >= emLen) { - return CX_INVALID_PARAMETER; - } - mDBlen = emLen - (hLen + 1); - if ((mLen + 2 * hLen + 2) >= emLen) { - return CX_INVALID_PARAMETER; - } - psLen = emLen - (mLen + 2 * hLen + 2); - - // random seed - cx_rng_no_throw(seed, hLen); - - // DB = lHash || PS || 01 || M - offset = 1 + hLen; - memcpy(em + offset, lHash, lHashLen); - offset += lHashLen; - memset(em + offset, 0, psLen); - offset += psLen; - em[offset] = 0x01; - offset++; - memcpy(em + offset, m, mLen); - - // 00 | masked seed || maskedDB - em[0] = 0x00; - - CX_CHECK(cx_pkcs1_MGF1(hID, seed, hLen, G_cx.pkcs1.MGF1, mDBlen)); - cx_memxor(em + 1 + hLen, G_cx.pkcs1.MGF1, mDBlen); - - CX_CHECK(cx_pkcs1_MGF1(hID, em + 1 + hLen, mDBlen, G_cx.pkcs1.MGF1, hLen)); - memcpy(em + 1, seed, hLen); - cx_memxor(em + 1, G_cx.pkcs1.MGF1, hLen); - - end: - return error; +cx_err_t cx_pkcs1_eme_oaep_encode(cx_md_t hID, + uint8_t *em, + size_t emLen, + const uint8_t *m, + size_t mLen) +{ + size_t mDBlen; + size_t psLen; + size_t offset; + uint8_t seed[64]; + size_t hLen; + const uint8_t *lHash; + size_t lHashLen; + cx_err_t error; + + hLen = cx_pkcs1_get_hash_len(hID); + lHash = cx_pkcs1_get_hash_oeap(hID, &lHashLen); + if (hLen == 0 || lHash == NULL) { + return CX_INVALID_PARAMETER; + } + + if ((hLen + 1) >= emLen) { + return CX_INVALID_PARAMETER; + } + mDBlen = emLen - (hLen + 1); + if ((mLen + 2 * hLen + 2) >= emLen) { + return CX_INVALID_PARAMETER; + } + psLen = emLen - (mLen + 2 * hLen + 2); + + // random seed + cx_rng_no_throw(seed, hLen); + + // DB = lHash || PS || 01 || M + offset = 1 + hLen; + memcpy(em + offset, lHash, lHashLen); + offset += lHashLen; + memset(em + offset, 0, psLen); + offset += psLen; + em[offset] = 0x01; + offset++; + memcpy(em + offset, m, mLen); + + // 00 | masked seed || maskedDB + em[0] = 0x00; + + CX_CHECK(cx_pkcs1_MGF1(hID, seed, hLen, G_cx.pkcs1.MGF1, mDBlen)); + cx_memxor(em + 1 + hLen, G_cx.pkcs1.MGF1, mDBlen); + + CX_CHECK(cx_pkcs1_MGF1(hID, em + 1 + hLen, mDBlen, G_cx.pkcs1.MGF1, hLen)); + memcpy(em + 1, seed, hLen); + cx_memxor(em + 1, G_cx.pkcs1.MGF1, hLen); + +end: + return error; } -cx_err_t cx_pkcs1_eme_oaep_decode(cx_md_t hID, uint8_t *em, size_t emLen, uint8_t *m, size_t *mLen) { - size_t mDBlen; - size_t offset; - size_t hLen; - const uint8_t *lHash; - size_t lHashLen; - cx_err_t error; - - hLen = cx_pkcs1_get_hash_len(hID); - lHash = cx_pkcs1_get_hash_oeap(hID, &lHashLen); - if (hLen == 0 || lHash == NULL) { - return CX_INVALID_PARAMETER; - } - if ((hLen + 1) >= emLen) { - return CX_INVALID_PARAMETER; - } - mDBlen = emLen - (hLen + 1); - - // unmask all - CX_CHECK(cx_pkcs1_MGF1(hID, em + 1 + hLen, mDBlen, G_cx.pkcs1.MGF1, hLen)); - cx_memxor(em + 1, G_cx.pkcs1.MGF1, hLen); - CX_CHECK(cx_pkcs1_MGF1(hID, em + 1, hLen, G_cx.pkcs1.MGF1, mDBlen)); - cx_memxor(em + 1 + hLen, G_cx.pkcs1.MGF1, mDBlen); - - // Y||seed||lHash||PS||01||M - if (em[0] != 0x00) { - return CX_INVALID_PARAMETER; - } - if (memcmp(em + 1 + hLen, lHash, hLen) != 0) { - return CX_INVALID_PARAMETER; - } - - for (offset = 1 + hLen + lHashLen; offset < emLen; offset++) { - if (em[offset] != 0) { - break; - } - } - if ((offset == emLen) || (em[offset] != 0x01)) { - return CX_INVALID_PARAMETER; - } - offset++; - - // copy M - if (*mLen < emLen - offset) { - return CX_INVALID_PARAMETER; - } - - *mLen = emLen - offset; - memmove(m, em + offset, *mLen); - - end: - return error; +cx_err_t cx_pkcs1_eme_oaep_decode(cx_md_t hID, uint8_t *em, size_t emLen, uint8_t *m, size_t *mLen) +{ + size_t mDBlen; + size_t offset; + size_t hLen; + const uint8_t *lHash; + size_t lHashLen; + cx_err_t error; + + hLen = cx_pkcs1_get_hash_len(hID); + lHash = cx_pkcs1_get_hash_oeap(hID, &lHashLen); + if (hLen == 0 || lHash == NULL) { + return CX_INVALID_PARAMETER; + } + if ((hLen + 1) >= emLen) { + return CX_INVALID_PARAMETER; + } + mDBlen = emLen - (hLen + 1); + + // unmask all + CX_CHECK(cx_pkcs1_MGF1(hID, em + 1 + hLen, mDBlen, G_cx.pkcs1.MGF1, hLen)); + cx_memxor(em + 1, G_cx.pkcs1.MGF1, hLen); + CX_CHECK(cx_pkcs1_MGF1(hID, em + 1, hLen, G_cx.pkcs1.MGF1, mDBlen)); + cx_memxor(em + 1 + hLen, G_cx.pkcs1.MGF1, mDBlen); + + // Y||seed||lHash||PS||01||M + if (em[0] != 0x00) { + return CX_INVALID_PARAMETER; + } + if (memcmp(em + 1 + hLen, lHash, hLen) != 0) { + return CX_INVALID_PARAMETER; + } + + for (offset = 1 + hLen + lHashLen; offset < emLen; offset++) { + if (em[offset] != 0) { + break; + } + } + if ((offset == emLen) || (em[offset] != 0x01)) { + return CX_INVALID_PARAMETER; + } + offset++; + + // copy M + if (*mLen < emLen - offset) { + return CX_INVALID_PARAMETER; + } + + *mLen = emLen - offset; + memmove(m, em + offset, *mLen); + +end: + return error; } #endif -#endif // HAVE_RSA +#endif // HAVE_RSA diff --git a/lib_cxng/src/cx_poly1305.c b/lib_cxng/src/cx_poly1305.c index ea883f926..58cb925bc 100644 --- a/lib_cxng/src/cx_poly1305.c +++ b/lib_cxng/src/cx_poly1305.c @@ -1,20 +1,20 @@ /******************************************************************************* -* Ledger Nano S - Secure firmware -* (c) 2022 Ledger -* -* Licensed under the Apache License, Version 2.0 (the "License"); -* you may not use this file except in compliance with the License. -* You may obtain a copy of the License at -* -* http://www.apache.org/licenses/LICENSE-2.0 -* -* Unless required by applicable law or agreed to in writing, software -* distributed under the License is distributed on an "AS IS" BASIS, -* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -* See the License for the specific language governing permissions and -* limitations under the License. -********************************************************************************/ + * Ledger Nano S - Secure firmware + * (c) 2022 Ledger + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT 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(HAVE_POLY1305) @@ -31,21 +31,38 @@ #define POLY1305_PADDED_BLOCK_SIZE (POLY1305_BLOCK_SIZE + 1) /* 2^130 - 5 */ -const uint8_t MODULUS[] = {0x3, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfb}; - -static void cx_le_bytes(const uint8_t *buf, uint8_t *le_buf, size_t len) { - size_t i; - for (i = 0; i < len; i++) { - le_buf[i] = buf[len - 1 - i]; - } +const uint8_t MODULUS[] = {0x3, + 0xff, + 0xff, + 0xff, + 0xff, + 0xff, + 0xff, + 0xff, + 0xff, + 0xff, + 0xff, + 0xff, + 0xff, + 0xff, + 0xff, + 0xff, + 0xfb}; + +static void cx_le_bytes(const uint8_t *buf, uint8_t *le_buf, size_t len) +{ + size_t i; + for (i = 0; i < len; i++) { + le_buf[i] = buf[len - 1 - i]; + } } static cx_err_t cx_poly1305_process(cx_poly1305_context_t *ctx, - size_t nblocks, - const uint8_t *input, - uint8_t needs_padding) { - size_t offset = 0; + size_t nblocks, + const uint8_t *input, + uint8_t needs_padding) +{ + size_t offset = 0; size_t i; cx_bn_t acc, r, p, d, res; uint8_t buf[POLY1305_PADDED_BLOCK_SIZE]; @@ -97,145 +114,147 @@ static cx_err_t cx_poly1305_process(cx_poly1305_context_t *ctx, offset += POLY1305_BLOCK_SIZE; } - end: - cx_bn_unlock(); - return error; +end: + cx_bn_unlock(); + return error; } -static cx_err_t cx_poly1305_compute_mac(cx_poly1305_context_t *ctx, uint8_t *tag) { - cx_err_t error; - cx_bn_t acc, s; - uint8_t buf[POLY1305_PADDED_BLOCK_SIZE]; - - CX_CHECK(cx_bn_lock(32, 0)); - CX_CHECK(cx_bn_alloc(&acc, 32)); - CX_CHECK(cx_bn_alloc(&s, 32)); - - buf[0] = (uint8_t) ctx->acc[4]; - U4BE_ENCODE(buf, 1, ctx->acc[3]); - U4BE_ENCODE(buf + 4 + 1, 0, ctx->acc[2]); - U4BE_ENCODE(buf + 8 + 1, 0, ctx->acc[1]); - U4BE_ENCODE(buf + 12 + 1, 0, ctx->acc[0]); - cx_bn_init(acc, buf, sizeof(buf)); - - U4BE_ENCODE(buf, 0, ctx->s[3]); - U4BE_ENCODE(buf + 4, 0, ctx->s[2]); - U4BE_ENCODE(buf + 8, 0, ctx->s[1]); - U4BE_ENCODE(buf + 12, 0, ctx->s[0]); - CX_CHECK(cx_bn_init(s, buf, POLY1305_BLOCK_SIZE)); - - /* Compute acc += s */ - CX_CHECK(cx_bn_add(acc, acc, s)); - - /* Compute MAC (128 least significant bits of the accumulator) */ - CX_CHECK(cx_bn_export(acc, buf, sizeof(MODULUS))); - cx_le_bytes(buf + 1, tag, POLY1305_BLOCK_SIZE); - - end: - cx_bn_unlock(); - return error; +static cx_err_t cx_poly1305_compute_mac(cx_poly1305_context_t *ctx, uint8_t *tag) +{ + cx_err_t error; + cx_bn_t acc, s; + uint8_t buf[POLY1305_PADDED_BLOCK_SIZE]; + + CX_CHECK(cx_bn_lock(32, 0)); + CX_CHECK(cx_bn_alloc(&acc, 32)); + CX_CHECK(cx_bn_alloc(&s, 32)); + + buf[0] = (uint8_t) ctx->acc[4]; + U4BE_ENCODE(buf, 1, ctx->acc[3]); + U4BE_ENCODE(buf + 4 + 1, 0, ctx->acc[2]); + U4BE_ENCODE(buf + 8 + 1, 0, ctx->acc[1]); + U4BE_ENCODE(buf + 12 + 1, 0, ctx->acc[0]); + cx_bn_init(acc, buf, sizeof(buf)); + + U4BE_ENCODE(buf, 0, ctx->s[3]); + U4BE_ENCODE(buf + 4, 0, ctx->s[2]); + U4BE_ENCODE(buf + 8, 0, ctx->s[1]); + U4BE_ENCODE(buf + 12, 0, ctx->s[0]); + CX_CHECK(cx_bn_init(s, buf, POLY1305_BLOCK_SIZE)); + + /* Compute acc += s */ + CX_CHECK(cx_bn_add(acc, acc, s)); + + /* Compute MAC (128 least significant bits of the accumulator) */ + CX_CHECK(cx_bn_export(acc, buf, sizeof(MODULUS))); + cx_le_bytes(buf + 1, tag, POLY1305_BLOCK_SIZE); + +end: + cx_bn_unlock(); + return error; } -void cx_poly1305_init(cx_poly1305_context_t *ctx) { - memset(ctx, 0, sizeof(cx_poly1305_context_t)); +void cx_poly1305_init(cx_poly1305_context_t *ctx) +{ + memset(ctx, 0, sizeof(cx_poly1305_context_t)); } -void cx_poly1305_set_key(cx_poly1305_context_t *ctx, const uint8_t *key) { - - /* r &= 0x0ffffffc0ffffffc0ffffffc0fffffff */ - ctx->r[0] = U4LE(key, 0) & 0x0FFFFFFF; - ctx->r[1] = U4LE(key, 4) & 0x0FFFFFFC; - ctx->r[2] = U4LE(key, 8) & 0x0FFFFFFC; - ctx->r[3] = U4LE(key, 12) & 0x0FFFFFFC; - ctx->s[0] = U4LE(key, 16); - ctx->s[1] = U4LE(key, 20); - ctx->s[2] = U4LE(key, 24); - ctx->s[3] = U4LE(key, 28); - /* Initial accumulator state */ - ctx->acc[0] = 0; - ctx->acc[1] = 0; - ctx->acc[2] = 0; - ctx->acc[3] = 0; - ctx->acc[4] = 0; - memset(ctx->block, 0, sizeof(ctx->block)); - ctx->block_len = 0; +void cx_poly1305_set_key(cx_poly1305_context_t *ctx, const uint8_t *key) +{ + /* r &= 0x0ffffffc0ffffffc0ffffffc0fffffff */ + ctx->r[0] = U4LE(key, 0) & 0x0FFFFFFF; + ctx->r[1] = U4LE(key, 4) & 0x0FFFFFFC; + ctx->r[2] = U4LE(key, 8) & 0x0FFFFFFC; + ctx->r[3] = U4LE(key, 12) & 0x0FFFFFFC; + ctx->s[0] = U4LE(key, 16); + ctx->s[1] = U4LE(key, 20); + ctx->s[2] = U4LE(key, 24); + ctx->s[3] = U4LE(key, 28); + /* Initial accumulator state */ + ctx->acc[0] = 0; + ctx->acc[1] = 0; + ctx->acc[2] = 0; + ctx->acc[3] = 0; + ctx->acc[4] = 0; + memset(ctx->block, 0, sizeof(ctx->block)); + ctx->block_len = 0; } -cx_err_t cx_poly1305_update(cx_poly1305_context_t *ctx, const uint8_t *input, size_t in_len) { - size_t offset = 0; - size_t remaining = in_len; - cx_err_t error = CX_OK; - size_t n; - - if ((remaining > 0) && (ctx->block_len > 0)) { - n = POLY1305_BLOCK_SIZE - ctx->block_len; - if (in_len < n) { - /* Not enough data to complete the block. - * Store this data with the other leftovers. - */ - memcpy(&ctx->block[ctx->block_len], input, in_len); - ctx->block_len += in_len; - remaining = 0; +cx_err_t cx_poly1305_update(cx_poly1305_context_t *ctx, const uint8_t *input, size_t in_len) +{ + size_t offset = 0; + size_t remaining = in_len; + cx_err_t error = CX_OK; + size_t n; + + if ((remaining > 0) && (ctx->block_len > 0)) { + n = POLY1305_BLOCK_SIZE - ctx->block_len; + if (in_len < n) { + /* Not enough data to complete the block. + * Store this data with the other leftovers. + */ + memcpy(&ctx->block[ctx->block_len], input, in_len); + ctx->block_len += in_len; + remaining = 0; + } + else { + /* Enough data to produce a complete block */ + memcpy(&ctx->block[ctx->block_len], input, n); + ctx->block_len = 0; + CX_CHECK(cx_poly1305_process(ctx, 1, ctx->block, 1)); /* add padding bit */ + offset += n; + remaining -= n; + } } - else { - /* Enough data to produce a complete block */ - memcpy(&ctx->block[ctx->block_len], input, n); - ctx->block_len = 0; - CX_CHECK(cx_poly1305_process(ctx, 1, ctx->block, 1)); /* add padding bit */ - offset += n; - remaining -= n; + + if (remaining >= POLY1305_BLOCK_SIZE) { + n = remaining / POLY1305_BLOCK_SIZE; + CX_CHECK(cx_poly1305_process(ctx, n, &input[offset], 1)); + offset += n * POLY1305_BLOCK_SIZE; + remaining %= POLY1305_BLOCK_SIZE; } - } - - if (remaining >= POLY1305_BLOCK_SIZE) { - n = remaining / POLY1305_BLOCK_SIZE; - CX_CHECK(cx_poly1305_process(ctx, n, &input[offset], 1)); - offset += n * POLY1305_BLOCK_SIZE; - remaining %= POLY1305_BLOCK_SIZE; - } - - if (remaining > 0) { - /* Store partial block */ - ctx->block_len = remaining; - memcpy(ctx->block, &input[offset], remaining); - } - - end: - return error; -} -cx_err_t cx_poly1305_finish(cx_poly1305_context_t *ctx, uint8_t *tag) { - cx_err_t error; - - /* Process any leftover data */ - if (ctx->block_len > 0) { - /* Add padding bit */ - ctx->block[ctx->block_len] = 1; - ctx->block_len++; - /* Pad with zeroes */ - memset( &ctx->block[ctx->block_len], 0, POLY1305_BLOCK_SIZE - ctx->block_len); - CX_CHECK(cx_poly1305_process(ctx, 1, ctx->block, 0)); - } - CX_CHECK(cx_poly1305_compute_mac(ctx, tag)); - - end: - return error; + if (remaining > 0) { + /* Store partial block */ + ctx->block_len = remaining; + memcpy(ctx->block, &input[offset], remaining); + } + +end: + return error; } -cx_err_t cx_poly1305_mac(const uint8_t *key, - const uint8_t *input, size_t in_len, - uint8_t *tag) { - cx_err_t error; - cx_poly1305_context_t *ctx = &G_cx.poly1305; - cx_poly1305_init(ctx); - cx_poly1305_set_key(ctx, key); - CX_CHECK(cx_poly1305_update(ctx, input, in_len)); - CX_CHECK(cx_poly1305_finish(ctx, tag)); +cx_err_t cx_poly1305_finish(cx_poly1305_context_t *ctx, uint8_t *tag) +{ + cx_err_t error; + + /* Process any leftover data */ + if (ctx->block_len > 0) { + /* Add padding bit */ + ctx->block[ctx->block_len] = 1; + ctx->block_len++; + /* Pad with zeroes */ + memset(&ctx->block[ctx->block_len], 0, POLY1305_BLOCK_SIZE - ctx->block_len); + CX_CHECK(cx_poly1305_process(ctx, 1, ctx->block, 0)); + } + CX_CHECK(cx_poly1305_compute_mac(ctx, tag)); end: - explicit_bzero(ctx, sizeof(cx_poly1305_context_t)); - return error; + return error; +} + +cx_err_t cx_poly1305_mac(const uint8_t *key, const uint8_t *input, size_t in_len, uint8_t *tag) +{ + cx_err_t error; + cx_poly1305_context_t *ctx = &G_cx.poly1305; + cx_poly1305_init(ctx); + cx_poly1305_set_key(ctx, key); + CX_CHECK(cx_poly1305_update(ctx, input, in_len)); + CX_CHECK(cx_poly1305_finish(ctx, tag)); +end: + explicit_bzero(ctx, sizeof(cx_poly1305_context_t)); + return error; } -#endif // HAVE_POLY1305 +#endif // HAVE_POLY1305 diff --git a/lib_cxng/src/cx_poly1305.h b/lib_cxng/src/cx_poly1305.h index 5c09e0da3..c85ef272f 100644 --- a/lib_cxng/src/cx_poly1305.h +++ b/lib_cxng/src/cx_poly1305.h @@ -1,23 +1,22 @@ /******************************************************************************* -* Ledger Nano S - Secure firmware -* (c) 2022 Ledger -* -* Licensed under the Apache License, Version 2.0 (the "License"); -* you may not use this file except in compliance with the License. -* You may obtain a copy of the License at -* -* http://www.apache.org/licenses/LICENSE-2.0 -* -* Unless required by applicable law or agreed to in writing, software -* distributed under the License is distributed on an "AS IS" BASIS, -* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -* See the License for the specific language governing permissions and -* limitations under the License. -********************************************************************************/ + * Ledger Nano S - Secure firmware + * (c) 2022 Ledger + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT 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(HAVE_POLY1305) - #ifndef CX_POLY1305_H #define CX_POLY1305_H @@ -25,7 +24,6 @@ #include "ox.h" #include - /** * @brief Initialize the specified Poly1305 context. * @@ -108,9 +106,7 @@ cx_err_t cx_poly1305_finish(cx_poly1305_context_t *ctx, uint8_t *tag); * * @return Error code */ -cx_err_t cx_poly1305_mac(const uint8_t *key, - const uint8_t *input, size_t in_len, - uint8_t *tag); +cx_err_t cx_poly1305_mac(const uint8_t *key, const uint8_t *input, size_t in_len, uint8_t *tag); -#endif /* CX_POLY1305_H */ -#endif // HAVE_POLY1305 +#endif /* CX_POLY1305_H */ +#endif // HAVE_POLY1305 diff --git a/lib_cxng/src/cx_ram.c b/lib_cxng/src/cx_ram.c index 907f4d226..ca041d636 100644 --- a/lib_cxng/src/cx_ram.c +++ b/lib_cxng/src/cx_ram.c @@ -1,20 +1,20 @@ /******************************************************************************* -* Ledger Nano S - Secure firmware -* (c) 2022 Ledger -* -* Licensed under the Apache License, Version 2.0 (the "License"); -* you may not use this file except in compliance with the License. -* You may obtain a copy of the License at -* -* http://www.apache.org/licenses/LICENSE-2.0 -* -* Unless required by applicable law or agreed to in writing, software -* distributed under the License is distributed on an "AS IS" BASIS, -* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -* See the License for the specific language governing permissions and -* limitations under the License. -********************************************************************************/ + * Ledger Nano S - Secure firmware + * (c) 2022 Ledger + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT 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 "cx_ram.h" diff --git a/lib_cxng/src/cx_ram.h b/lib_cxng/src/cx_ram.h index 3d53f383f..b86a649f8 100644 --- a/lib_cxng/src/cx_ram.h +++ b/lib_cxng/src/cx_ram.h @@ -1,20 +1,20 @@ /******************************************************************************* -* Ledger Nano S - Secure firmware -* (c) 2022 Ledger -* -* Licensed under the Apache License, Version 2.0 (the "License"); -* you may not use this file except in compliance with the License. -* You may obtain a copy of the License at -* -* http://www.apache.org/licenses/LICENSE-2.0 -* -* Unless required by applicable law or agreed to in writing, software -* distributed under the License is distributed on an "AS IS" BASIS, -* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -* See the License for the specific language governing permissions and -* limitations under the License. -********************************************************************************/ + * Ledger Nano S - Secure firmware + * (c) 2022 Ledger + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT 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 CX_RAM_H #define CX_RAM_H @@ -42,76 +42,75 @@ union cx_u { /* PBKDF internal hash */ #ifdef HAVE_PBKDF2 - cx_pbkdf2_t pbkdf2; + cx_pbkdf2_t pbkdf2; #endif - /* RSA internal PKCS1 */ + /* RSA internal PKCS1 */ #ifdef HAVE_RSA - cx_pkcs1_t pkcs1; + cx_pkcs1_t pkcs1; #endif /* hash & hmac */ #ifdef HAVE_HASH - cx_hash_t hash_ctx; + cx_hash_t hash_ctx; #if defined(HAVE_SHA256) || defined(HAVE_SHA224) - cx_sha256_t sha256; + cx_sha256_t sha256; #endif #if defined(HAVE_SHA512) || defined(HAVE_SHA384) - cx_sha512_t sha512; + cx_sha512_t sha512; #endif #if defined(HAVE_SHA3) - cx_sha3_t sha3; + cx_sha3_t sha3; #endif #if defined(HAVE_BLAKE2) - cx_xblake_t blake; + cx_xblake_t blake; #endif #if defined(HAVE_GROESTL) - cx_xgroestl_t groestl; + cx_xgroestl_t groestl; #endif #if defined(HAVE_RIPEMD160) - cx_ripemd160_t ripemd160; -#endif // HAVE_RIPEMD160 + cx_ripemd160_t ripemd160; +#endif // HAVE_RIPEMD160 #endif #if defined(HAVE_BLAKE3) - cx_blake3_t blake3; -#endif // HAVE_BLAKE3 + cx_blake3_t blake3; +#endif // HAVE_BLAKE3 #ifdef HAVE_HMAC - cx_hmac_t hmac; + cx_hmac_t hmac; #if defined(HAVE_HMAC) && (defined(HAVE_SHA512) || defined(HAVE_SHA384)) - cx_hmac_sha512_t hmac_sha512; + cx_hmac_sha512_t hmac_sha512; #endif #if defined(HAVE_HMAC) && (defined(HAVE_SHA256) || defined(HAVE_SHA224)) - cx_hmac_sha256_t hmac_sha256; + cx_hmac_sha256_t hmac_sha256; #endif #endif #ifdef HAVE_RNG_RFC6979 - cx_rnd_rfc6979_ctx_t rfc6979; + cx_rnd_rfc6979_ctx_t rfc6979; #endif #ifdef HAVE_POLY1305 - cx_poly1305_context_t poly1305; -#endif // HAVE_POLY1305 + cx_poly1305_context_t poly1305; +#endif // HAVE_POLY1305 #ifdef HAVE_CHACHA - cx_chacha_context_t chacha; -#endif // HAVE_CHACHA - cx_cipher_context_t cipher; + cx_chacha_context_t chacha; +#endif // HAVE_CHACHA + cx_cipher_context_t cipher; #ifdef HAVE_CMAC - cx_cmac_context_t cmac; -#endif // HAVE_CMAC - + cx_cmac_context_t cmac; +#endif // HAVE_CMAC }; extern union cx_u G_cx; diff --git a/lib_cxng/src/cx_ripemd160.c b/lib_cxng/src/cx_ripemd160.c index f11751555..e72801ce0 100644 --- a/lib_cxng/src/cx_ripemd160.c +++ b/lib_cxng/src/cx_ripemd160.c @@ -1,20 +1,20 @@ /******************************************************************************* -* Ledger Nano S - Secure firmware -* (c) 2022 Ledger -* -* Licensed under the Apache License, Version 2.0 (the "License"); -* you may not use this file except in compliance with the License. -* You may obtain a copy of the License at -* -* http://www.apache.org/licenses/LICENSE-2.0 -* -* Unless required by applicable law or agreed to in writing, software -* distributed under the License is distributed on an "AS IS" BASIS, -* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -* See the License for the specific language governing permissions and -* limitations under the License. -********************************************************************************/ + * Ledger Nano S - Secure firmware + * (c) 2022 Ledger + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + ********************************************************************************/ #ifdef HAVE_RIPEMD160 @@ -29,17 +29,16 @@ #define RIPEMD_BLOCK_SIZE 64 -const cx_hash_info_t cx_ripemd160_info = { - CX_RIPEMD160, - CX_RIPEMD160_SIZE, - RIPEMD_BLOCK_SIZE, - sizeof(cx_ripemd160_t), - (cx_err_t (*)(cx_hash_t *ctx))cx_ripemd160_init_no_throw, - (cx_err_t (*)(cx_hash_t *ctx, const uint8_t *data, size_t len))cx_ripemd160_update, - (cx_err_t (*)(cx_hash_t *ctx, uint8_t *digest))cx_ripemd160_final, - NULL, - NULL - }; +const cx_hash_info_t cx_ripemd160_info + = {CX_RIPEMD160, + CX_RIPEMD160_SIZE, + RIPEMD_BLOCK_SIZE, + sizeof(cx_ripemd160_t), + (cx_err_t(*)(cx_hash_t * ctx)) cx_ripemd160_init_no_throw, + (cx_err_t(*)(cx_hash_t * ctx, const uint8_t *data, size_t len)) cx_ripemd160_update, + (cx_err_t(*)(cx_hash_t * ctx, uint8_t *digest)) cx_ripemd160_final, + NULL, + NULL}; /* ----------------------------------------------------------------------- */ /* */ @@ -78,16 +77,17 @@ static const uint8_t sR[] = { /*sR[64..79]*/ 8, 5, 12, 9, 12, 5, 14, 6, 8, 13, 6, 5, 15, 13, 11, 11, }; -static const uint32_t hzero[] = {0x67452301UL, 0xEFCDAB89UL, 0x98BADCFEUL, 0x10325476UL, 0xC3D2E1F0UL}; +static const uint32_t hzero[] + = {0x67452301UL, 0xEFCDAB89UL, 0x98BADCFEUL, 0x10325476UL, 0xC3D2E1F0UL}; // additive constante -#define kL_0_15 0x00000000UL +#define kL_0_15 0x00000000UL #define kL_16_31 0x5A827999UL #define kL_32_47 0x6ED9EBA1UL #define kL_48_63 0x8F1BBCDCUL #define kL_64_78 0xA953FD4EUL -#define kR_0_15 0x50A28BE6UL +#define kR_0_15 0x50A28BE6UL #define kR_16_31 0x5C4DD124UL #define kR_32_47 0x6D703EF3UL #define kR_48_63 0x7A6D76E9UL @@ -96,20 +96,25 @@ static const uint32_t hzero[] = {0x67452301UL, 0xEFCDAB89UL, 0x98BADCFEUL, 0x103 #define x BCD[0] #define y BCD[1] #define z BCD[2] -static unsigned long int f1(uint32_t *BCD) { - return ((x) ^ (y) ^ (z)); +static unsigned long int f1(uint32_t *BCD) +{ + return ((x) ^ (y) ^ (z)); } -static unsigned long int f2(uint32_t *BCD) { - return (((x) & (y)) | ((~x) & (z))); +static unsigned long int f2(uint32_t *BCD) +{ + return (((x) & (y)) | ((~x) & (z))); } -static unsigned long int f3(uint32_t *BCD) { - return (((x) | (~(y))) ^ (z)); +static unsigned long int f3(uint32_t *BCD) +{ + return (((x) | (~(y))) ^ (z)); } -static unsigned long int f4(uint32_t *BCD) { - return (((x) & (z)) | ((y) & (~(z)))); +static unsigned long int f4(uint32_t *BCD) +{ + return (((x) & (z)) | ((y) & (~(z)))); } -static unsigned long int f5(uint32_t *BCD) { - return ((x) ^ ((y) | (~(z)))); +static unsigned long int f5(uint32_t *BCD) +{ + return ((x) ^ ((y) | (~(z)))); } #undef x #undef y @@ -117,23 +122,24 @@ static unsigned long int f5(uint32_t *BCD) { #define rotL(x, n) cx_rotl(x, n) -cx_err_t cx_ripemd160_init_no_throw(cx_ripemd160_t *hash) { - memset(hash, 0, sizeof(cx_ripemd160_t)); - hash->header.info = &cx_ripemd160_info; - memmove(hash->acc, hzero, sizeof(hzero)); - return CX_OK; +cx_err_t cx_ripemd160_init_no_throw(cx_ripemd160_t *hash) +{ + memset(hash, 0, sizeof(cx_ripemd160_t)); + hash->header.info = &cx_ripemd160_info; + memmove(hash->acc, hzero, sizeof(hzero)); + return CX_OK; } +static void cx_ripemd160_block(cx_ripemd160_t *hash) +{ + uint8_t j; + uint32_t Tl; + uint32_t Tr; -static void cx_ripemd160_block(cx_ripemd160_t *hash) { - uint8_t j; - uint32_t Tl; - uint32_t Tr; - - uint32_t ACCl[5]; - uint32_t ACCr[5]; - uint32_t *accumulator; - uint32_t *X; + uint32_t ACCl[5]; + uint32_t ACCr[5]; + uint32_t *accumulator; + uint32_t *X; #define Al ACCl[0] #define Bl ACCl[1] @@ -147,160 +153,164 @@ static void cx_ripemd160_block(cx_ripemd160_t *hash) { #define Dr ACCr[3] #define Er ACCr[4] - // init - X = (uint32_t *)&hash->block[0]; - accumulator = (uint32_t *)&hash->acc[0]; - memmove(ACCl, accumulator, sizeof(ACCl)); - memmove(ACCr, accumulator, sizeof(ACCr)); + // init + X = (uint32_t *) &hash->block[0]; + accumulator = (uint32_t *) &hash->acc[0]; + memmove(ACCl, accumulator, sizeof(ACCl)); + memmove(ACCr, accumulator, sizeof(ACCr)); #ifdef ARCH_BIG_ENDIAN - cx_swap_buffer32(X, 16); + cx_swap_buffer32(X, 16); #endif - for (j = 0; j < 80; j++) { - Tl = Al + X[zL[j]]; - Tr = Ar + X[zR[j]]; - switch (j >> 4) { - case 0: - Tl += f1(&Bl) + kL_0_15; - Tr += f5(&Br) + kR_0_15; - break; - case 1: - Tl += f2(&Bl) + kL_16_31; - Tr += f4(&Br) + kR_16_31; - break; - case 2: - Tl += f3(&Bl) + kL_32_47; - Tr += f3(&Br) + kR_32_47; - break; - case 3: - Tl += f4(&Bl) + kL_48_63; - Tr += f2(&Br) + kR_48_63; - break; - case 4: - Tl += f5(&Bl) + kL_64_78; - Tr += f1(&Br) + kR_64_78; - break; - default: - break; + for (j = 0; j < 80; j++) { + Tl = Al + X[zL[j]]; + Tr = Ar + X[zR[j]]; + switch (j >> 4) { + case 0: + Tl += f1(&Bl) + kL_0_15; + Tr += f5(&Br) + kR_0_15; + break; + case 1: + Tl += f2(&Bl) + kL_16_31; + Tr += f4(&Br) + kR_16_31; + break; + case 2: + Tl += f3(&Bl) + kL_32_47; + Tr += f3(&Br) + kR_32_47; + break; + case 3: + Tl += f4(&Bl) + kL_48_63; + Tr += f2(&Br) + kR_48_63; + break; + case 4: + Tl += f5(&Bl) + kL_64_78; + Tr += f1(&Br) + kR_64_78; + break; + default: + break; + } + + Tl = rotL(Tl, sL[j]); + Tl += El; + Al = El; + El = Dl; + Dl = rotL(Cl, 10); + Cl = Bl; + Bl = Tl; + + Tr = rotL(Tr, sR[j]); + Tr += Er; + Ar = Er; + Er = Dr; + Dr = rotL(Cr, 10); + Cr = Br; + Br = Tr; } - Tl = rotL(Tl, sL[j]); - Tl += El; - Al = El; - El = Dl; - Dl = rotL(Cl, 10); - Cl = Bl; - Bl = Tl; - - Tr = rotL(Tr, sR[j]); - Tr += Er; - Ar = Er; - Er = Dr; - Dr = rotL(Cr, 10); - Cr = Br; - Br = Tr; - } - - //(update chaining values) - Tl = accumulator[1] + Cl + Dr; - accumulator[1] = accumulator[2] + Dl + Er; - accumulator[2] = accumulator[3] + El + Ar; - accumulator[3] = accumulator[4] + Al + Br; - accumulator[4] = accumulator[0] + Bl + Cr; - accumulator[0] = Tl; + //(update chaining values) + Tl = accumulator[1] + Cl + Dr; + accumulator[1] = accumulator[2] + Dl + Er; + accumulator[2] = accumulator[3] + El + Ar; + accumulator[3] = accumulator[4] + Al + Br; + accumulator[4] = accumulator[0] + Bl + Cr; + accumulator[0] = Tl; } -cx_err_t cx_ripemd160_update(cx_ripemd160_t *ctx, const uint8_t *data, size_t len) { - if (ctx == NULL) { - return CX_INVALID_PARAMETER; - } - if (data == NULL && len != 0) { - return CX_INVALID_PARAMETER; - } - - unsigned int r; - uint8_t block_size; - uint8_t * block; - unsigned int blen; - - block_size = 64; - block = ctx->block; - blen = ctx->blen; - ctx->blen = 0; - - if (blen >= block_size) { - return CX_INVALID_PARAMETER; - } - - // --- append input data and process all blocks --- - if ((blen + len) >= block_size) { - r = block_size - blen; - do { - if (ctx->header.counter == CX_HASH_MAX_BLOCK_COUNT) { +cx_err_t cx_ripemd160_update(cx_ripemd160_t *ctx, const uint8_t *data, size_t len) +{ + if (ctx == NULL) { return CX_INVALID_PARAMETER; - } - memcpy(block + blen, data, r); - cx_ripemd160_block(ctx); - blen = 0; - ctx->header.counter++; - data += r; - len -= r; - r = block_size; - } while (len >= block_size); - } - - // --- remind rest data--- - memcpy(block + blen, data, len); - blen += len; - ctx->blen = blen; - return CX_OK; -} + } + if (data == NULL && len != 0) { + return CX_INVALID_PARAMETER; + } -cx_err_t cx_ripemd160_final(cx_ripemd160_t *ctx, uint8_t *digest) { - uint8_t * block; - unsigned int blen; - unsigned long int bitlen; + unsigned int r; + uint8_t block_size; + uint8_t *block; + unsigned int blen; - block = ctx->block; - blen = ctx->blen; + block_size = 64; + block = ctx->block; + blen = ctx->blen; + ctx->blen = 0; - // one more block? - block[blen] = 0x80; - blen++; - bitlen = (((unsigned long int)ctx->header.counter) * 64UL + (unsigned long int)blen - 1UL) * 8UL; + if (blen >= block_size) { + return CX_INVALID_PARAMETER; + } - // one more block? - if (64 - blen < 8) { + // --- append input data and process all blocks --- + if ((blen + len) >= block_size) { + r = block_size - blen; + do { + if (ctx->header.counter == CX_HASH_MAX_BLOCK_COUNT) { + return CX_INVALID_PARAMETER; + } + memcpy(block + blen, data, r); + cx_ripemd160_block(ctx); + blen = 0; + ctx->header.counter++; + data += r; + len -= r; + r = block_size; + } while (len >= block_size); + } + + // --- remind rest data--- + memcpy(block + blen, data, len); + blen += len; + ctx->blen = blen; + return CX_OK; +} + +cx_err_t cx_ripemd160_final(cx_ripemd160_t *ctx, uint8_t *digest) +{ + uint8_t *block; + unsigned int blen; + unsigned long int bitlen; + + block = ctx->block; + blen = ctx->blen; + + // one more block? + block[blen] = 0x80; + blen++; + bitlen + = (((unsigned long int) ctx->header.counter) * 64UL + (unsigned long int) blen - 1UL) * 8UL; + + // one more block? + if (64 - blen < 8) { + memset(block + blen, 0, (64 - blen)); + cx_ripemd160_block(ctx); + blen = 0; + } + // last block! memset(block + blen, 0, (64 - blen)); - cx_ripemd160_block(ctx); - blen = 0; - } - // last block! - memset(block + blen, 0, (64 - blen)); #ifdef ARCH_BIG_ENDIAN - (*(unsigned long int *)(&block[64 - 8])) = cx_swap_uint32(bitlen); + (*(unsigned long int *) (&block[64 - 8])) = cx_swap_uint32(bitlen); #else - (*(uint64_t *)(&block[64 - 8])) = bitlen; + (*(uint64_t *) (&block[64 - 8])) = bitlen; #endif - cx_ripemd160_block(ctx); - // provide result + cx_ripemd160_block(ctx); + // provide result #ifdef ARCH_BIG_ENDIAN - cx_swap_buffer32((unsigned long int *)acc, 5); + cx_swap_buffer32((unsigned long int *) acc, 5); #endif - memcpy(digest, ctx->acc, CX_RIPEMD160_SIZE); - return CX_OK; + memcpy(digest, ctx->acc, CX_RIPEMD160_SIZE); + return CX_OK; } -size_t cx_hash_ripemd160(const uint8_t *in, size_t in_len, uint8_t *out, size_t out_len) { - if (out_len < CX_RIPEMD160_SIZE) { - return 0; - } - cx_ripemd160_init_no_throw(&G_cx.ripemd160); - cx_ripemd160_update(&G_cx.ripemd160, in, in_len); - cx_ripemd160_final(&G_cx.ripemd160, out); - explicit_bzero(&G_cx.ripemd160, sizeof(cx_ripemd160_t)); - return CX_RIPEMD160_SIZE; +size_t cx_hash_ripemd160(const uint8_t *in, size_t in_len, uint8_t *out, size_t out_len) +{ + if (out_len < CX_RIPEMD160_SIZE) { + return 0; + } + cx_ripemd160_init_no_throw(&G_cx.ripemd160); + cx_ripemd160_update(&G_cx.ripemd160, in, in_len); + cx_ripemd160_final(&G_cx.ripemd160, out); + explicit_bzero(&G_cx.ripemd160, sizeof(cx_ripemd160_t)); + return CX_RIPEMD160_SIZE; } -#endif // HAVE_RIPEMD160 +#endif // HAVE_RIPEMD160 diff --git a/lib_cxng/src/cx_ripemd160.h b/lib_cxng/src/cx_ripemd160.h index bdb579f1e..96621601a 100644 --- a/lib_cxng/src/cx_ripemd160.h +++ b/lib_cxng/src/cx_ripemd160.h @@ -12,6 +12,6 @@ extern const cx_hash_info_t cx_ripemd160_info; cx_err_t cx_ripemd160_update(cx_ripemd160_t *ctx, const uint8_t *data, size_t len); cx_err_t cx_ripemd160_final(cx_ripemd160_t *ctx, uint8_t *digest); -#endif // HAVE_RIPEMD160 +#endif // HAVE_RIPEMD160 -#endif // CX_RIPEMD160_H +#endif // CX_RIPEMD160_H diff --git a/lib_cxng/src/cx_rng.c b/lib_cxng/src/cx_rng.c index f463b2e4a..1a5ddaacd 100644 --- a/lib_cxng/src/cx_rng.c +++ b/lib_cxng/src/cx_rng.c @@ -1,20 +1,20 @@ /******************************************************************************* -* Ledger Nano S - Secure firmware -* (c) 2022 Ledger -* -* Licensed under the Apache License, Version 2.0 (the "License"); -* you may not use this file except in compliance with the License. -* You may obtain a copy of the License at -* -* http://www.apache.org/licenses/LICENSE-2.0 -* -* Unless required by applicable law or agreed to in writing, software -* distributed under the License is distributed on an "AS IS" BASIS, -* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -* See the License for the specific language governing permissions and -* limitations under the License. -********************************************************************************/ + * Ledger Nano S - Secure firmware + * (c) 2022 Ledger + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + ********************************************************************************/ #ifdef HAVE_RNG @@ -30,32 +30,35 @@ #include "os_random.h" #include -void cx_rng_no_throw(uint8_t *buffer, size_t len) { - cx_err_t error; +void cx_rng_no_throw(uint8_t *buffer, size_t len) +{ + cx_err_t error; - error = cx_get_random_bytes(buffer, len); - if (error) { - /* XXX: calling halt() add a dependency to THROW (os_longjmp). */ - while (1); - } + error = cx_get_random_bytes(buffer, len); + if (error) { + /* XXX: calling halt() add a dependency to THROW (os_longjmp). */ + while (1) + ; + } } -uint32_t cx_rng_u32_range_func(uint32_t a, uint32_t b, cx_rng_u32_range_randfunc_t randfunc) { - uint32_t range = b - a; - uint32_t r; - - if ((range & (range - 1)) == 0) { // special case: range is a power of 2 - r = randfunc(); - return a + r % range; - } - - uint32_t chunk_size = UINT32_MAX / range; - uint32_t last_chunk_value = chunk_size * range; - r = randfunc(); - while (r >= last_chunk_value) { - r = randfunc(); - } - return a + r / chunk_size; +uint32_t cx_rng_u32_range_func(uint32_t a, uint32_t b, cx_rng_u32_range_randfunc_t randfunc) +{ + uint32_t range = b - a; + uint32_t r; + + if ((range & (range - 1)) == 0) { // special case: range is a power of 2 + r = randfunc(); + return a + r % range; + } + + uint32_t chunk_size = UINT32_MAX / range; + uint32_t last_chunk_value = chunk_size * range; + r = randfunc(); + while (r >= last_chunk_value) { + r = randfunc(); + } + return a + r / chunk_size; } -#endif // HAVE_RNG +#endif // HAVE_RNG diff --git a/lib_cxng/src/cx_rng.h b/lib_cxng/src/cx_rng.h index 152bd9eb7..06941e0f7 100644 --- a/lib_cxng/src/cx_rng.h +++ b/lib_cxng/src/cx_rng.h @@ -1,20 +1,20 @@ /******************************************************************************* -* Ledger Nano S - Secure firmware -* (c) 2022 Ledger -* -* Licensed under the Apache License, Version 2.0 (the "License"); -* you may not use this file except in compliance with the License. -* You may obtain a copy of the License at -* -* http://www.apache.org/licenses/LICENSE-2.0 -* -* Unless required by applicable law or agreed to in writing, software -* distributed under the License is distributed on an "AS IS" BASIS, -* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -* See the License for the specific language governing permissions and -* limitations under the License. -********************************************************************************/ + * Ledger Nano S - Secure firmware + * (c) 2022 Ledger + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + ********************************************************************************/ #ifdef HAVE_RNG #ifndef CX_RNG_H @@ -33,4 +33,4 @@ void cx_trng_lengthtest(void); #endif -#endif // HAVE_RNG +#endif // HAVE_RNG diff --git a/lib_cxng/src/cx_rng_rfc6979.c b/lib_cxng/src/cx_rng_rfc6979.c index 409be408d..6920f57a2 100644 --- a/lib_cxng/src/cx_rng_rfc6979.c +++ b/lib_cxng/src/cx_rng_rfc6979.c @@ -1,20 +1,20 @@ /******************************************************************************* -* Ledger Nano S - Secure firmware -* (c) 2022 Ledger -* -* Licensed under the Apache License, Version 2.0 (the "License"); -* you may not use this file except in compliance with the License. -* You may obtain a copy of the License at -* -* http://www.apache.org/licenses/LICENSE-2.0 -* -* Unless required by applicable law or agreed to in writing, software -* distributed under the License is distributed on an "AS IS" BASIS, -* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -* See the License for the specific language governing permissions and -* limitations under the License. -********************************************************************************/ + * Ledger Nano S - Secure firmware + * (c) 2022 Ledger + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + ********************************************************************************/ #ifdef HAVE_RNG_RFC6979 @@ -35,14 +35,15 @@ /* b : first operand */ /* len: bytes length of a,b and r */ /* ----------------------------------------------------------------------- */ -static void cx_rfc6979_sub(uint8_t *r, uint8_t *a, uint8_t *b, size_t len) { - uint32_t c; - c = 0; - while (len--) { - c = a[len]-b[len]-c; - r[len] = c&0xFF; - c = c&0xFFFFFF00?1:0; - } +static void cx_rfc6979_sub(uint8_t *r, uint8_t *a, uint8_t *b, size_t len) +{ + uint32_t c; + c = 0; + while (len--) { + c = a[len] - b[len] - c; + r[len] = c & 0xFF; + c = c & 0xFFFFFF00 ? 1 : 0; + } } /* ----------------------------------------------------------------------- */ @@ -54,33 +55,39 @@ static void cx_rfc6979_sub(uint8_t *r, uint8_t *a, uint8_t *b, size_t len) { /* b : b string to convert */ /* b_len: bits length os b, shall be multiple of 8, true by design */ /* ----------------------------------------------------------------------- */ -static size_t cx_rfc6979_bits2int(cx_rnd_rfc6979_ctx_t *rfc_ctx, const uint8_t *b, size_t b_len, uint8_t *b_out) { - if (b_len > rfc_ctx->q_len) { - uint8_t right_shift = (b_len - rfc_ctx->q_len) & 7; - // For example copy a SHA384 digest in a 256-bit buffer: 384 > 256 - // bits2int copy the high 256 bits from b into b_out - if (right_shift == 0) { - // Easy case: copy bytes directly - memmove(b_out, b, rfc_ctx->r_len >> 3); - } else { - // Shift bits of b from (b_len - rfc_ctx->q_len) bytes to the right, into b_out - uint8_t carry = 0; - size_t i, rlen = rfc_ctx->r_len >> 3; - - for (i = 0; i < rlen; i++) { - uint8_t x = b[i]; - b_out[i] = carry | (x >> right_shift); - carry = (x << (8 - right_shift)) & 0xff; - } +static size_t cx_rfc6979_bits2int(cx_rnd_rfc6979_ctx_t *rfc_ctx, + const uint8_t *b, + size_t b_len, + uint8_t *b_out) +{ + if (b_len > rfc_ctx->q_len) { + uint8_t right_shift = (b_len - rfc_ctx->q_len) & 7; + // For example copy a SHA384 digest in a 256-bit buffer: 384 > 256 + // bits2int copy the high 256 bits from b into b_out + if (right_shift == 0) { + // Easy case: copy bytes directly + memmove(b_out, b, rfc_ctx->r_len >> 3); + } + else { + // Shift bits of b from (b_len - rfc_ctx->q_len) bytes to the right, into b_out + uint8_t carry = 0; + size_t i, rlen = rfc_ctx->r_len >> 3; + + for (i = 0; i < rlen; i++) { + uint8_t x = b[i]; + b_out[i] = carry | (x >> right_shift); + carry = (x << (8 - right_shift)) & 0xff; + } + } + } + else { + // Pad b with zeros + b_len = b_len >> 3; + size_t padding_len = (rfc_ctx->r_len >> 3) - b_len; + memset(b_out, 0, padding_len); + memmove(b_out + padding_len, b, b_len); } - } else { - // Pad b with zeros - b_len = b_len >> 3; - size_t padding_len = (rfc_ctx->r_len >> 3) - b_len; - memset(b_out, 0, padding_len); - memmove(b_out + padding_len, b, b_len); - } - return rfc_ctx->r_len; + return rfc_ctx->r_len; } /* ----------------------------------------------------------------------- */ @@ -92,11 +99,15 @@ static size_t cx_rfc6979_bits2int(cx_rnd_rfc6979_ctx_t *rfc_ctx, const uint8_t * /* b : b string to convert */ /* b_len: bits length os b, shall be multiple of 8, true by design */ /* ----------------------------------------------------------------------- */ -static void cx_rfc6979_bits2octets(cx_rnd_rfc6979_ctx_t *rfc_ctx, const uint8_t *b, size_t b_len, uint8_t *b_out) { - cx_rfc6979_bits2int(rfc_ctx, b, b_len, b_out); - if (memcmp(b_out, rfc_ctx->q, rfc_ctx->r_len>>3)>0) { - cx_rfc6979_sub(b_out, b_out, rfc_ctx->q, rfc_ctx->r_len>>3); - } +static void cx_rfc6979_bits2octets(cx_rnd_rfc6979_ctx_t *rfc_ctx, + const uint8_t *b, + size_t b_len, + uint8_t *b_out) +{ + cx_rfc6979_bits2int(rfc_ctx, b, b_len, b_out); + if (memcmp(b_out, rfc_ctx->q, rfc_ctx->r_len >> 3) > 0) { + cx_rfc6979_sub(b_out, b_out, rfc_ctx->q, rfc_ctx->r_len >> 3); + } } /* ----------------------------------------------------------------------- */ @@ -106,19 +117,24 @@ static void cx_rfc6979_bits2octets(cx_rnd_rfc6979_ctx_t *rfc_ctx, const uint8_t /* i : integer to convert */ /* i_len: bits length os i, shall be multiple of 8, true by design */ /* ----------------------------------------------------------------------- */ -static void cx_rfc6979_int2octets(cx_rnd_rfc6979_ctx_t *rfc_ctx, const uint8_t *i, size_t i_len, uint8_t *b_out) { - int32_t delta; - delta = (i_len>>3) - (rfc_ctx->r_len>>3); - if (delta < 0) { - delta = -delta; - memcpy(b_out+delta, i, i_len>>3); - while(delta--) { - b_out[delta] = 0; +static void cx_rfc6979_int2octets(cx_rnd_rfc6979_ctx_t *rfc_ctx, + const uint8_t *i, + size_t i_len, + uint8_t *b_out) +{ + int32_t delta; + delta = (i_len >> 3) - (rfc_ctx->r_len >> 3); + if (delta < 0) { + delta = -delta; + memcpy(b_out + delta, i, i_len >> 3); + while (delta--) { + b_out[delta] = 0; + } + } + else { + // assume first bytes are null + memcpy(b_out, i + delta, rfc_ctx->r_len >> 3); } - } else { - // assume first bytes are null - memcpy(b_out,i+delta, rfc_ctx->r_len>>3); - } } /* ----------------------------------------------------------------------- */ @@ -128,157 +144,177 @@ static void cx_rfc6979_int2octets(cx_rnd_rfc6979_ctx_t *rfc_ctx, const uint8_t * /* b : b */ /* b_len: bytes length b */ /* ----------------------------------------------------------------------- */ -static uint32_t cx_rfc6979_bitslength(const uint8_t *a, size_t a_len) { - uint8_t b; - - while (*a == 0) { - a++; - a_len--; - if (a_len == 0) { - return 0; +static uint32_t cx_rfc6979_bitslength(const uint8_t *a, size_t a_len) +{ + uint8_t b; + + while (*a == 0) { + a++; + a_len--; + if (a_len == 0) { + return 0; + } } - } - //note: here len != 0 && *a != 0 - a_len = a_len * 8; - b = *a; - while ((b & 0x80) == 0) { - a_len--; - b = b << 1; - } - return a_len; + // note: here len != 0 && *a != 0 + a_len = a_len * 8; + b = *a; + while ((b & 0x80) == 0) { + a_len--; + b = b << 1; + } + return a_len; } static void cx_rfc6979_hmacVK(cx_rnd_rfc6979_ctx_t *rfc_ctx, - int8_t opt, - const uint8_t *x, size_t x_len, - const uint8_t *h1, size_t h1_len, - /*const uint8_t *additional_input, size_t additional_input_len,*/ - uint8_t *out) { - size_t len; - - len = rfc_ctx->md_len; - cx_hmac_init(&rfc_ctx->hmac, rfc_ctx->hash_id, rfc_ctx->k, rfc_ctx->md_len); - if (opt>=0) { - rfc_ctx->v[rfc_ctx->md_len] = opt; - len ++; - } - cx_hmac_update(&rfc_ctx->hmac, rfc_ctx->v, len); - if (x) { - cx_rfc6979_int2octets(rfc_ctx, x, x_len*8, rfc_ctx->tmp); - cx_hmac_update(&rfc_ctx->hmac, rfc_ctx->tmp, rfc_ctx->r_len>>3); - } - if (h1) { - cx_rfc6979_bits2octets(rfc_ctx, h1, h1_len*8, rfc_ctx->tmp); - cx_hmac_update(&rfc_ctx->hmac, rfc_ctx->tmp, rfc_ctx->r_len>>3); - } - /* - if (additional_input) { - cx_hmac_update(&rfc_ctx->hmac, additional_input, additional_input_len); - } - */ - len = rfc_ctx->md_len; - cx_hmac_final(&rfc_ctx->hmac, out, &len); - + int8_t opt, + const uint8_t *x, + size_t x_len, + const uint8_t *h1, + size_t h1_len, + /*const uint8_t *additional_input, size_t additional_input_len,*/ + uint8_t *out) +{ + size_t len; + + len = rfc_ctx->md_len; + cx_hmac_init(&rfc_ctx->hmac, rfc_ctx->hash_id, rfc_ctx->k, rfc_ctx->md_len); + if (opt >= 0) { + rfc_ctx->v[rfc_ctx->md_len] = opt; + len++; + } + cx_hmac_update(&rfc_ctx->hmac, rfc_ctx->v, len); + if (x) { + cx_rfc6979_int2octets(rfc_ctx, x, x_len * 8, rfc_ctx->tmp); + cx_hmac_update(&rfc_ctx->hmac, rfc_ctx->tmp, rfc_ctx->r_len >> 3); + } + if (h1) { + cx_rfc6979_bits2octets(rfc_ctx, h1, h1_len * 8, rfc_ctx->tmp); + cx_hmac_update(&rfc_ctx->hmac, rfc_ctx->tmp, rfc_ctx->r_len >> 3); + } + /* + if (additional_input) { + cx_hmac_update(&rfc_ctx->hmac, additional_input, additional_input_len); + } + */ + len = rfc_ctx->md_len; + cx_hmac_final(&rfc_ctx->hmac, out, &len); } -cx_err_t cx_rng_rfc6979_init(cx_rnd_rfc6979_ctx_t *rfc_ctx, cx_md_t hash_id, - const uint8_t *x, size_t x_len, - const uint8_t *h1, size_t h1_len, - const uint8_t *q, size_t q_len - /*const uint8_t *additional_input, size_t additional_input_len*/) { - - const cx_hash_info_t *hash_info = cx_hash_get_info(hash_id); - if (hash_info == NULL || hash_info->output_size == 0) { - return CX_INVALID_PARAMETER; - } +cx_err_t cx_rng_rfc6979_init(cx_rnd_rfc6979_ctx_t *rfc_ctx, + cx_md_t hash_id, + const uint8_t *x, + size_t x_len, + const uint8_t *h1, + size_t h1_len, + const uint8_t *q, + size_t q_len + /*const uint8_t *additional_input, size_t additional_input_len*/) +{ + const cx_hash_info_t *hash_info = cx_hash_get_info(hash_id); + if (hash_info == NULL || hash_info->output_size == 0) { + return CX_INVALID_PARAMETER; + } - //setup params - memcpy(rfc_ctx->q, q, q_len); - rfc_ctx->q_len = cx_rfc6979_bitslength(q, q_len); - rfc_ctx->r_len = (rfc_ctx->q_len+7) & ~7; - rfc_ctx->hash_id = hash_id; - rfc_ctx->md_len = hash_info->output_size; + // setup params + memcpy(rfc_ctx->q, q, q_len); + rfc_ctx->q_len = cx_rfc6979_bitslength(q, q_len); + rfc_ctx->r_len = (rfc_ctx->q_len + 7) & ~7; + rfc_ctx->hash_id = hash_id; + rfc_ctx->md_len = hash_info->output_size; - //STEP A: h1 = HASH(m) - // input is h1 + // STEP A: h1 = HASH(m) + // input is h1 - //Step B: V = 0x01...01 @digest_len - memset(rfc_ctx->v, 0x01, rfc_ctx->md_len); + // Step B: V = 0x01...01 @digest_len + memset(rfc_ctx->v, 0x01, rfc_ctx->md_len); - //Step C: K = 0x00...00 @digest_len - memset(rfc_ctx->k, 0x00, rfc_ctx->md_len); + // Step C: K = 0x00...00 @digest_len + memset(rfc_ctx->k, 0x00, rfc_ctx->md_len); - //Step D: K = HMAC (K, V || 0x00 || int2octets(x) || bits2octetc(h1) [ || additional_input]) - cx_rfc6979_hmacVK(rfc_ctx, 0, x, x_len, h1, h1_len, rfc_ctx->k /*, additional_input, additional_input_len*/); + // Step D: K = HMAC (K, V || 0x00 || int2octets(x) || bits2octetc(h1) [ || additional_input]) + cx_rfc6979_hmacVK( + rfc_ctx, 0, x, x_len, h1, h1_len, rfc_ctx->k /*, additional_input, additional_input_len*/); - //Step E: V = HMAC (K, V). - cx_rfc6979_hmacVK(rfc_ctx, -1, NULL, 0, NULL, 0, rfc_ctx->v); + // Step E: V = HMAC (K, V). + cx_rfc6979_hmacVK(rfc_ctx, -1, NULL, 0, NULL, 0, rfc_ctx->v); - //Step F: K = HMAC (K, V || 0x01 || int2octets(x) || bits2octetc(h1) [ || additional_input]) - cx_rfc6979_hmacVK(rfc_ctx, 0x01, x, x_len, h1, h1_len, rfc_ctx->k /*, additional_input, additional_input_len*/); + // Step F: K = HMAC (K, V || 0x01 || int2octets(x) || bits2octetc(h1) [ || additional_input]) + cx_rfc6979_hmacVK(rfc_ctx, + 0x01, + x, + x_len, + h1, + h1_len, + rfc_ctx->k /*, additional_input, additional_input_len*/); - //Step G: V = HMAC (K, V). - cx_rfc6979_hmacVK(rfc_ctx, -1, NULL, 0, NULL, 0, rfc_ctx->v); + // Step G: V = HMAC (K, V). + cx_rfc6979_hmacVK(rfc_ctx, -1, NULL, 0, NULL, 0, rfc_ctx->v); - return CX_OK; + return CX_OK; } -cx_err_t cx_rng_rfc6979_next(cx_rnd_rfc6979_ctx_t *rfc_ctx, - uint8_t *out, size_t out_len) { - size_t t_Blen; - size_t r_Blen; - bool found; - - if ((out_len*8) < rfc_ctx->r_len) { - return CX_INVALID_PARAMETER; - } - - r_Blen = rfc_ctx->r_len>>3; - found = false; - while (!found) { - // Step H1: - t_Blen = 0; +cx_err_t cx_rng_rfc6979_next(cx_rnd_rfc6979_ctx_t *rfc_ctx, uint8_t *out, size_t out_len) +{ + size_t t_Blen; + size_t r_Blen; + bool found; - // Step H2: - // while t_Blenv); - if (rfc_ctx->md_len > (r_Blen-t_Blen)) { - memcpy(out+t_Blen, rfc_ctx->v, r_Blen-t_Blen); - t_Blen = r_Blen; - } else { - memcpy(out+t_Blen, rfc_ctx->v, rfc_ctx->md_len); - t_Blen += rfc_ctx->md_len; - } + if ((out_len * 8) < rfc_ctx->r_len) { + return CX_INVALID_PARAMETER; } - //STEP H3: k = bits2int(T) - cx_rfc6979_bits2int(rfc_ctx, out, t_Blen*8, out); - if(memcmp(out, rfc_ctx->q, rfc_ctx->r_len>>3)<0) { - found = true; + r_Blen = rfc_ctx->r_len >> 3; + found = false; + while (!found) { + // Step H1: + t_Blen = 0; + + // Step H2: + // while t_Blenv); + if (rfc_ctx->md_len > (r_Blen - t_Blen)) { + memcpy(out + t_Blen, rfc_ctx->v, r_Blen - t_Blen); + t_Blen = r_Blen; + } + else { + memcpy(out + t_Blen, rfc_ctx->v, rfc_ctx->md_len); + t_Blen += rfc_ctx->md_len; + } + } + + // STEP H3: k = bits2int(T) + cx_rfc6979_bits2int(rfc_ctx, out, t_Blen * 8, out); + if (memcmp(out, rfc_ctx->q, rfc_ctx->r_len >> 3) < 0) { + found = true; + } + + // STEP H3 bis: + // K = HMAC (K, V || 0). + cx_rfc6979_hmacVK(rfc_ctx, 0, NULL, 0, NULL, 0, rfc_ctx->k); + // V = HMAC (K, V). + cx_rfc6979_hmacVK(rfc_ctx, -1, NULL, 0, NULL, 0, rfc_ctx->v); } - // STEP H3 bis: - // K = HMAC (K, V || 0). - cx_rfc6979_hmacVK(rfc_ctx, 0, NULL, 0, NULL, 0, rfc_ctx->k); - // V = HMAC (K, V). - cx_rfc6979_hmacVK(rfc_ctx, -1, NULL, 0, NULL, 0, rfc_ctx->v); - } - - return CX_OK; + return CX_OK; } -cx_err_t cx_rng_rfc6979(cx_md_t hash_id, - const uint8_t *x, size_t x_len, - const uint8_t *h1, size_t h1_len, - const uint8_t *q, size_t q_len, - uint8_t *out, size_t out_len) { - cx_err_t error; - CX_CHECK(cx_rng_rfc6979_init(&G_cx.rfc6979, hash_id, x, x_len, h1, h1_len,q, q_len)); - CX_CHECK(cx_rng_rfc6979_next(&G_cx.rfc6979, out, out_len)); - end: - return error; +cx_err_t cx_rng_rfc6979(cx_md_t hash_id, + const uint8_t *x, + size_t x_len, + const uint8_t *h1, + size_t h1_len, + const uint8_t *q, + size_t q_len, + uint8_t *out, + size_t out_len) +{ + cx_err_t error; + CX_CHECK(cx_rng_rfc6979_init(&G_cx.rfc6979, hash_id, x, x_len, h1, h1_len, q, q_len)); + CX_CHECK(cx_rng_rfc6979_next(&G_cx.rfc6979, out, out_len)); +end: + return error; } -#endif //HAVE_RNG_RFC6979 +#endif // HAVE_RNG_RFC6979 diff --git a/lib_cxng/src/cx_rng_rfc6979.h b/lib_cxng/src/cx_rng_rfc6979.h index 7bda09546..b7e37b411 100644 --- a/lib_cxng/src/cx_rng_rfc6979.h +++ b/lib_cxng/src/cx_rng_rfc6979.h @@ -1,20 +1,20 @@ /******************************************************************************* -* Ledger Nano S - Secure firmware -* (c) 2022 Ledger -* -* Licensed under the Apache License, Version 2.0 (the "License"); -* you may not use this file except in compliance with the License. -* You may obtain a copy of the License at -* -* http://www.apache.org/licenses/LICENSE-2.0 -* -* Unless required by applicable law or agreed to in writing, software -* distributed under the License is distributed on an "AS IS" BASIS, -* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -* See the License for the specific language governing permissions and -* limitations under the License. -********************************************************************************/ + * Ledger Nano S - Secure firmware + * (c) 2022 Ledger + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + ********************************************************************************/ #ifdef HAVE_RNG_RFC6979 @@ -26,45 +26,49 @@ #include #include -#define CX_RFC6979_BUFFER_LENGTH 64 -#define CX_RFC6979_MAX_RLEN 66 +#define CX_RFC6979_BUFFER_LENGTH 64 +#define CX_RFC6979_MAX_RLEN 66 typedef struct { - uint8_t v[CX_RFC6979_BUFFER_LENGTH + 1]; - uint8_t k[CX_RFC6979_BUFFER_LENGTH]; - uint8_t q[CX_RFC6979_MAX_RLEN]; - uint32_t q_len; - uint32_t r_len; - uint8_t tmp[CX_RFC6979_MAX_RLEN]; - cx_md_t hash_id; - size_t md_len; + uint8_t v[CX_RFC6979_BUFFER_LENGTH + 1]; + uint8_t k[CX_RFC6979_BUFFER_LENGTH]; + uint8_t q[CX_RFC6979_MAX_RLEN]; + uint32_t q_len; + uint32_t r_len; + uint8_t tmp[CX_RFC6979_MAX_RLEN]; + cx_md_t hash_id; + size_t md_len; - union { - #if (!defined(HAVE_SHA512) && !defined(HAVE_SHA384) && !defined(HAVE_SHA256) && !defined(HAVE_SHA224)) || !defined(HAVE_HMAC) - #error No hmac defined for rfc6979 support - #endif + union { +#if (!defined(HAVE_SHA512) && !defined(HAVE_SHA384) && !defined(HAVE_SHA256) \ + && !defined(HAVE_SHA224)) \ + || !defined(HAVE_HMAC) +#error No hmac defined for rfc6979 support +#endif - cx_hmac_t hmac; + cx_hmac_t hmac; - #if defined(HAVE_SHA512) || defined(HAVE_SHA384) - cx_hmac_sha512_t hmac_sha512; - #endif +#if defined(HAVE_SHA512) || defined(HAVE_SHA384) + cx_hmac_sha512_t hmac_sha512; +#endif - #if defined(HAVE_SHA256) || defined(HAVE_SHA224) - cx_hmac_sha256_t hmac_sha256; - #endif - }; +#if defined(HAVE_SHA256) || defined(HAVE_SHA224) + cx_hmac_sha256_t hmac_sha256; +#endif + }; } cx_rnd_rfc6979_ctx_t; cx_err_t cx_rng_rfc6979_init(cx_rnd_rfc6979_ctx_t *rfc_ctx, - cx_md_t hash_id, - const uint8_t *x, size_t x_len, - const uint8_t *h1, size_t h1_len, - const uint8_t *q, size_t q_len + cx_md_t hash_id, + const uint8_t *x, + size_t x_len, + const uint8_t *h1, + size_t h1_len, + const uint8_t *q, + size_t q_len /*const uint8_t *additional_input, size_t additional_input_len*/); -cx_err_t cx_rng_rfc6979_next(cx_rnd_rfc6979_ctx_t *rfc_ctx, - uint8_t *out, size_t out_len); -#endif //CX_HMAC_DRBG_H +cx_err_t cx_rng_rfc6979_next(cx_rnd_rfc6979_ctx_t *rfc_ctx, uint8_t *out, size_t out_len); +#endif // CX_HMAC_DRBG_H -#endif //HAVE_RNG_RFC6979 +#endif // HAVE_RNG_RFC6979 diff --git a/lib_cxng/src/cx_rsa.c b/lib_cxng/src/cx_rsa.c index 51b973a1f..dfa90480c 100644 --- a/lib_cxng/src/cx_rsa.c +++ b/lib_cxng/src/cx_rsa.c @@ -1,20 +1,20 @@ /******************************************************************************* -* Ledger Nano S - Secure firmware -* (c) 2022 Ledger -* -* Licensed under the Apache License, Version 2.0 (the "License"); -* you may not use this file except in compliance with the License. -* You may obtain a copy of the License at -* -* http://www.apache.org/licenses/LICENSE-2.0 -* -* Unless required by applicable law or agreed to in writing, software -* distributed under the License is distributed on an "AS IS" BASIS, -* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -* See the License for the specific language governing permissions and -* limitations under the License. -********************************************************************************/ + * Ledger Nano S - Secure firmware + * (c) 2022 Ledger + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + ********************************************************************************/ #ifdef HAVE_RSA @@ -30,483 +30,503 @@ static cx_err_t modulus_valid(size_t modulus_len) { - switch (modulus_len) { - case 128: - case 256: - case 384: - case 512: - return CX_OK; - default: - return CX_INVALID_PARAMETER; - } + switch (modulus_len) { + case 128: + case 256: + case 384: + case 512: + return CX_OK; + default: + return CX_INVALID_PARAMETER; + } } -cx_err_t cx_rsa_private_key_ctx_size(const cx_rsa_private_key_t *key, size_t *size) { - switch (key->size) { - case 128: - *size = sizeof(cx_rsa_1024_private_key_t); - break; - case 256: - *size = sizeof(cx_rsa_2048_private_key_t); - break; - case 384: - *size = sizeof(cx_rsa_3072_private_key_t); - break; - case 512: - *size = sizeof(cx_rsa_4096_private_key_t); - break; - default: - return CX_INVALID_PARAMETER; - } - - return CX_OK; +cx_err_t cx_rsa_private_key_ctx_size(const cx_rsa_private_key_t *key, size_t *size) +{ + switch (key->size) { + case 128: + *size = sizeof(cx_rsa_1024_private_key_t); + break; + case 256: + *size = sizeof(cx_rsa_2048_private_key_t); + break; + case 384: + *size = sizeof(cx_rsa_3072_private_key_t); + break; + case 512: + *size = sizeof(cx_rsa_4096_private_key_t); + break; + default: + return CX_INVALID_PARAMETER; + } + + return CX_OK; } -cx_err_t cx_rsa_get_public_components(const cx_rsa_public_key_t *key, uint8_t **e, uint8_t **n) { - switch (key->size) { - case 128: - *e = ((cx_rsa_1024_public_key_t *)key)->e; - *n = ((cx_rsa_1024_public_key_t *)key)->n; - break; - case 256: - *e = ((cx_rsa_2048_public_key_t *)key)->e; - *n = ((cx_rsa_2048_public_key_t *)key)->n; - break; - case 384: - *e = ((cx_rsa_3072_public_key_t *)key)->e; - *n = ((cx_rsa_3072_public_key_t *)key)->n; - break; - case 512: - *e = ((cx_rsa_4096_public_key_t *)key)->e; - *n = ((cx_rsa_4096_public_key_t *)key)->n; - break; - default: - return CX_INVALID_PARAMETER; - } - return CX_OK; +cx_err_t cx_rsa_get_public_components(const cx_rsa_public_key_t *key, uint8_t **e, uint8_t **n) +{ + switch (key->size) { + case 128: + *e = ((cx_rsa_1024_public_key_t *) key)->e; + *n = ((cx_rsa_1024_public_key_t *) key)->n; + break; + case 256: + *e = ((cx_rsa_2048_public_key_t *) key)->e; + *n = ((cx_rsa_2048_public_key_t *) key)->n; + break; + case 384: + *e = ((cx_rsa_3072_public_key_t *) key)->e; + *n = ((cx_rsa_3072_public_key_t *) key)->n; + break; + case 512: + *e = ((cx_rsa_4096_public_key_t *) key)->e; + *n = ((cx_rsa_4096_public_key_t *) key)->n; + break; + default: + return CX_INVALID_PARAMETER; + } + return CX_OK; } -cx_err_t cx_rsa_get_private_components(const cx_rsa_private_key_t *key, uint8_t **d, uint8_t **n) { - switch (key->size) { - case 128: - *d = ((cx_rsa_1024_private_key_t *)key)->d; - *n = ((cx_rsa_1024_private_key_t *)key)->n; - break; - case 256: - *d = ((cx_rsa_2048_private_key_t *)key)->d; - *n = ((cx_rsa_2048_private_key_t *)key)->n; - break; - case 384: - *d = ((cx_rsa_3072_private_key_t *)key)->d; - *n = ((cx_rsa_3072_private_key_t *)key)->n; - break; - case 512: - *d = ((cx_rsa_4096_private_key_t *)key)->d; - *n = ((cx_rsa_4096_private_key_t *)key)->n; - break; - default: - return CX_INVALID_PARAMETER; - } - return CX_OK; +cx_err_t cx_rsa_get_private_components(const cx_rsa_private_key_t *key, uint8_t **d, uint8_t **n) +{ + switch (key->size) { + case 128: + *d = ((cx_rsa_1024_private_key_t *) key)->d; + *n = ((cx_rsa_1024_private_key_t *) key)->n; + break; + case 256: + *d = ((cx_rsa_2048_private_key_t *) key)->d; + *n = ((cx_rsa_2048_private_key_t *) key)->n; + break; + case 384: + *d = ((cx_rsa_3072_private_key_t *) key)->d; + *n = ((cx_rsa_3072_private_key_t *) key)->n; + break; + case 512: + *d = ((cx_rsa_4096_private_key_t *) key)->d; + *n = ((cx_rsa_4096_private_key_t *) key)->n; + break; + default: + return CX_INVALID_PARAMETER; + } + return CX_OK; } -cx_err_t cx_rsa_init_public_key_no_throw(const uint8_t * exponent, - size_t exponent_len, - const uint8_t * modulus, - size_t modulus_len, - cx_rsa_public_key_t *key) { - cx_err_t error; - uint8_t *e; - uint8_t *n; - - if (!(((exponent == NULL) && (exponent_len == 0)) || ((exponent) && (exponent_len <= 4)))) { - return CX_INVALID_PARAMETER; - } - if (!(((modulus == NULL) && (modulus_len == 0)) || (modulus))) { - return CX_INVALID_PARAMETER; - } - if (key == NULL) { - return CX_INVALID_PARAMETER; - } - - CX_CHECK(modulus_valid(modulus_len)); - key->size = modulus_len; - - CX_CHECK(cx_rsa_get_public_components(key, &e, &n)); - - if (modulus && exponent) { - memset(e, 0, 4); - memmove(e + (4 - exponent_len), exponent, exponent_len); - memmove(n, modulus, modulus_len); - } else { - memset(n, 0, modulus_len); - memset(e, 0, 4); - } - - end: - return error; +cx_err_t cx_rsa_init_public_key_no_throw(const uint8_t *exponent, + size_t exponent_len, + const uint8_t *modulus, + size_t modulus_len, + cx_rsa_public_key_t *key) +{ + cx_err_t error; + uint8_t *e; + uint8_t *n; + + if (!(((exponent == NULL) && (exponent_len == 0)) || ((exponent) && (exponent_len <= 4)))) { + return CX_INVALID_PARAMETER; + } + if (!(((modulus == NULL) && (modulus_len == 0)) || (modulus))) { + return CX_INVALID_PARAMETER; + } + if (key == NULL) { + return CX_INVALID_PARAMETER; + } + + CX_CHECK(modulus_valid(modulus_len)); + key->size = modulus_len; + + CX_CHECK(cx_rsa_get_public_components(key, &e, &n)); + + if (modulus && exponent) { + memset(e, 0, 4); + memmove(e + (4 - exponent_len), exponent, exponent_len); + memmove(n, modulus, modulus_len); + } + else { + memset(n, 0, modulus_len); + memset(e, 0, 4); + } + +end: + return error; } -cx_err_t cx_rsa_init_private_key_no_throw(const uint8_t * exponent, - size_t exponent_len, - const uint8_t * modulus, - size_t modulus_len, - cx_rsa_private_key_t *key) { - cx_err_t error; - uint8_t *d; - uint8_t *n; - - if (!(((exponent == NULL) && (exponent_len == 0)) || (exponent))) { - return CX_INVALID_PARAMETER; - } - if (!(((modulus == NULL) && (modulus_len == 0)) || (modulus))) { - return CX_INVALID_PARAMETER; - } - if (exponent_len != modulus_len) { - return CX_INVALID_PARAMETER; - } - if (key == NULL) { - return CX_INVALID_PARAMETER; - } - - CX_CHECK(modulus_valid(modulus_len)); - key->size = modulus_len; - - CX_CHECK(cx_rsa_get_private_components(key, &d, &n)); - - if (modulus && exponent) { - memmove(d, exponent, modulus_len); - memmove(n, modulus, modulus_len); - } else { - memset(d, 0, modulus_len); - memset(n, 0, modulus_len); - } - - end: - return error; +cx_err_t cx_rsa_init_private_key_no_throw(const uint8_t *exponent, + size_t exponent_len, + const uint8_t *modulus, + size_t modulus_len, + cx_rsa_private_key_t *key) +{ + cx_err_t error; + uint8_t *d; + uint8_t *n; + + if (!(((exponent == NULL) && (exponent_len == 0)) || (exponent))) { + return CX_INVALID_PARAMETER; + } + if (!(((modulus == NULL) && (modulus_len == 0)) || (modulus))) { + return CX_INVALID_PARAMETER; + } + if (exponent_len != modulus_len) { + return CX_INVALID_PARAMETER; + } + if (key == NULL) { + return CX_INVALID_PARAMETER; + } + + CX_CHECK(modulus_valid(modulus_len)); + key->size = modulus_len; + + CX_CHECK(cx_rsa_get_private_components(key, &d, &n)); + + if (modulus && exponent) { + memmove(d, exponent, modulus_len); + memmove(n, modulus, modulus_len); + } + else { + memset(d, 0, modulus_len); + memset(n, 0, modulus_len); + } + +end: + return error; } static const uint8_t C_default_e[] = {0x00, 0x01, 0x00, 0x01}; cx_err_t cx_rsa_generate_pair_no_throw(size_t modulus_len, - cx_rsa_public_key_t * public_key, - cx_rsa_private_key_t *private_key, - const uint8_t * exponent, - size_t exponent_len, - const uint8_t * externalPQ) { - cx_bn_t bn_p, bn_q, bn_n; - cx_err_t error; - uint8_t *pv_d; - uint8_t *pv_n; - uint8_t *pu_e; - uint8_t *pu_n; - size_t size; - - if (!(((exponent == NULL) && (exponent_len == 0)) || ((exponent) && (exponent_len <= 4)))) { - return CX_INVALID_PARAMETER; - } - if (!((public_key != NULL) && (private_key != NULL))) { - return CX_INVALID_PARAMETER; - } - - CX_CHECK(modulus_valid(modulus_len)); - - private_key->size = modulus_len; - public_key->size = modulus_len; - CX_CHECK(cx_rsa_get_private_components(private_key, &pv_d, &pv_n)); - CX_CHECK(cx_rsa_get_public_components(public_key, &pu_e, &pu_n)); - - size = modulus_len / 2; - - CX_CHECK(cx_bn_lock(size, 0)); - CX_CHECK(cx_bn_alloc(&bn_p, size)); - CX_CHECK(cx_bn_alloc(&bn_q, size)); - // gen prime - if (externalPQ) { - CX_CHECK(cx_bn_init(bn_p, externalPQ, size)); - CX_CHECK(cx_bn_init(bn_q, externalPQ + size, size)); - } else { - CX_CHECK(cx_bn_rand(bn_p)); - CX_CHECK(cx_bn_set_bit(bn_p, size * 8 - 1)); - CX_CHECK(cx_bn_set_bit(bn_p, size * 8 - 2)); - CX_CHECK(cx_bn_rand(bn_q)); - CX_CHECK(cx_bn_set_bit(bn_q, size * 8 - 1)); - CX_CHECK(cx_bn_set_bit(bn_q, size * 8 - 2)); - CX_CHECK(cx_bn_next_prime(bn_p)); - CX_CHECK(cx_bn_next_prime(bn_q)); - } - - // public key: - CX_CHECK(cx_bn_alloc(&bn_n, modulus_len)); - CX_CHECK(cx_bn_mul(bn_n, bn_p, bn_q)); - CX_CHECK(cx_bn_export(bn_n, pu_n, modulus_len)); - if (exponent == NULL) { - exponent = C_default_e; - exponent_len = sizeof(C_default_e); - } - memmove(pu_e + (4 - exponent_len), exponent, exponent_len); - CX_CHECK(cx_bn_destroy(&bn_n)); - - // private key: - // - n=(p-1)(q-1) - CX_CHECK(cx_bn_alloc(&bn_n, size)); - CX_CHECK(cx_bn_set_u32(bn_n, 1)); - CX_CHECK_IGNORE_CARRY(cx_bn_sub(bn_p, bn_p, bn_n)); - CX_CHECK_IGNORE_CARRY(cx_bn_sub(bn_q, bn_q, bn_n)); - CX_CHECK(cx_bn_destroy(&bn_n)); - CX_CHECK(cx_bn_alloc(&bn_n, modulus_len)); - CX_CHECK(cx_bn_mul(bn_n, bn_p, bn_q)); - CX_CHECK(cx_bn_destroy(&bn_p)); - CX_CHECK(cx_bn_destroy(&bn_q)); - // - d = inv(e) mod n - CX_CHECK(cx_bn_alloc(&bn_p, modulus_len)); - cx_bn_mod_u32_invert(bn_p, (pu_e[0] << 24) | (pu_e[1] << 16) | (pu_e[2] << 8) | (pu_e[3] << 0), bn_n); - CX_CHECK(cx_bn_export(bn_p, pv_d, modulus_len)); - memmove(pv_n, pu_n, modulus_len); - - end: - cx_bn_unlock(); - return error; + cx_rsa_public_key_t *public_key, + cx_rsa_private_key_t *private_key, + const uint8_t *exponent, + size_t exponent_len, + const uint8_t *externalPQ) +{ + cx_bn_t bn_p, bn_q, bn_n; + cx_err_t error; + uint8_t *pv_d; + uint8_t *pv_n; + uint8_t *pu_e; + uint8_t *pu_n; + size_t size; + + if (!(((exponent == NULL) && (exponent_len == 0)) || ((exponent) && (exponent_len <= 4)))) { + return CX_INVALID_PARAMETER; + } + if (!((public_key != NULL) && (private_key != NULL))) { + return CX_INVALID_PARAMETER; + } + + CX_CHECK(modulus_valid(modulus_len)); + + private_key->size = modulus_len; + public_key->size = modulus_len; + CX_CHECK(cx_rsa_get_private_components(private_key, &pv_d, &pv_n)); + CX_CHECK(cx_rsa_get_public_components(public_key, &pu_e, &pu_n)); + + size = modulus_len / 2; + + CX_CHECK(cx_bn_lock(size, 0)); + CX_CHECK(cx_bn_alloc(&bn_p, size)); + CX_CHECK(cx_bn_alloc(&bn_q, size)); + // gen prime + if (externalPQ) { + CX_CHECK(cx_bn_init(bn_p, externalPQ, size)); + CX_CHECK(cx_bn_init(bn_q, externalPQ + size, size)); + } + else { + CX_CHECK(cx_bn_rand(bn_p)); + CX_CHECK(cx_bn_set_bit(bn_p, size * 8 - 1)); + CX_CHECK(cx_bn_set_bit(bn_p, size * 8 - 2)); + CX_CHECK(cx_bn_rand(bn_q)); + CX_CHECK(cx_bn_set_bit(bn_q, size * 8 - 1)); + CX_CHECK(cx_bn_set_bit(bn_q, size * 8 - 2)); + CX_CHECK(cx_bn_next_prime(bn_p)); + CX_CHECK(cx_bn_next_prime(bn_q)); + } + + // public key: + CX_CHECK(cx_bn_alloc(&bn_n, modulus_len)); + CX_CHECK(cx_bn_mul(bn_n, bn_p, bn_q)); + CX_CHECK(cx_bn_export(bn_n, pu_n, modulus_len)); + if (exponent == NULL) { + exponent = C_default_e; + exponent_len = sizeof(C_default_e); + } + memmove(pu_e + (4 - exponent_len), exponent, exponent_len); + CX_CHECK(cx_bn_destroy(&bn_n)); + + // private key: + // - n=(p-1)(q-1) + CX_CHECK(cx_bn_alloc(&bn_n, size)); + CX_CHECK(cx_bn_set_u32(bn_n, 1)); + CX_CHECK_IGNORE_CARRY(cx_bn_sub(bn_p, bn_p, bn_n)); + CX_CHECK_IGNORE_CARRY(cx_bn_sub(bn_q, bn_q, bn_n)); + CX_CHECK(cx_bn_destroy(&bn_n)); + CX_CHECK(cx_bn_alloc(&bn_n, modulus_len)); + CX_CHECK(cx_bn_mul(bn_n, bn_p, bn_q)); + CX_CHECK(cx_bn_destroy(&bn_p)); + CX_CHECK(cx_bn_destroy(&bn_q)); + // - d = inv(e) mod n + CX_CHECK(cx_bn_alloc(&bn_p, modulus_len)); + cx_bn_mod_u32_invert( + bn_p, (pu_e[0] << 24) | (pu_e[1] << 16) | (pu_e[2] << 8) | (pu_e[3] << 0), bn_n); + CX_CHECK(cx_bn_export(bn_p, pv_d, modulus_len)); + memmove(pv_n, pu_n, modulus_len); + +end: + cx_bn_unlock(); + return error; } cx_err_t cx_rsa_sign_with_salt_len(const cx_rsa_private_key_t *key, uint32_t mode, cx_md_t hashID, - const uint8_t * hash, + const uint8_t *hash, size_t hash_len, - uint8_t * sig, + uint8_t *sig, size_t sig_len, - size_t salt_len) { - uint8_t *key_d; - uint8_t *key_n; - cx_bn_t bn_n, bn_msg, bn_r; - uint32_t nbits; - cx_err_t error; - - // cx_scc_struct_check_rsa_privkey(key); - if (!(hash && (hash_len <= key->size))) { - return CX_INVALID_PARAMETER; - } - if (!(sig && (sig_len >= key->size))) { - return CX_INVALID_PARAMETER; - } - - CX_CHECK(cx_rsa_get_private_components(key, &key_d, &key_n)); - CX_CHECK(cx_bn_lock(key->size, 0)); - CX_CHECK(cx_bn_alloc(&bn_r, key->size)); - CX_CHECK(cx_bn_alloc_init(&bn_n, key->size, key_n, key->size)); - - // encode - switch (mode & CX_MASK_PAD) { - case CX_PAD_PKCS1_1o5: - sig_len = key->size; - CX_CHECK(cx_pkcs1_emsa_v1o5_encode(hashID, sig, sig_len, hash, hash_len)); - break; - case CX_PAD_PKCS1_PSS: - CX_CHECK(cx_bn_cnt_bits(bn_n, &nbits)); - CX_CHECK(cx_pkcs1_emsa_pss_encode_with_salt_len(hashID, sig, nbits - 1, hash, hash_len, salt_len, &sig_len)); - break; - default: - error = CX_INVALID_PARAMETER; - goto end; - } - - // encrypt - CX_CHECK(cx_bn_alloc_init(&bn_msg, key->size, sig, sig_len)); - CX_CHECK(cx_bn_mod_pow2(bn_r, bn_msg, key_d, key->size, bn_n)); - CX_CHECK(cx_bn_export(bn_r, sig, key->size)); - - end: - cx_bn_unlock(); - return error; + size_t salt_len) +{ + uint8_t *key_d; + uint8_t *key_n; + cx_bn_t bn_n, bn_msg, bn_r; + uint32_t nbits; + cx_err_t error; + + // cx_scc_struct_check_rsa_privkey(key); + if (!(hash && (hash_len <= key->size))) { + return CX_INVALID_PARAMETER; + } + if (!(sig && (sig_len >= key->size))) { + return CX_INVALID_PARAMETER; + } + + CX_CHECK(cx_rsa_get_private_components(key, &key_d, &key_n)); + CX_CHECK(cx_bn_lock(key->size, 0)); + CX_CHECK(cx_bn_alloc(&bn_r, key->size)); + CX_CHECK(cx_bn_alloc_init(&bn_n, key->size, key_n, key->size)); + + // encode + switch (mode & CX_MASK_PAD) { + case CX_PAD_PKCS1_1o5: + sig_len = key->size; + CX_CHECK(cx_pkcs1_emsa_v1o5_encode(hashID, sig, sig_len, hash, hash_len)); + break; + case CX_PAD_PKCS1_PSS: + CX_CHECK(cx_bn_cnt_bits(bn_n, &nbits)); + CX_CHECK(cx_pkcs1_emsa_pss_encode_with_salt_len( + hashID, sig, nbits - 1, hash, hash_len, salt_len, &sig_len)); + break; + default: + error = CX_INVALID_PARAMETER; + goto end; + } + + // encrypt + CX_CHECK(cx_bn_alloc_init(&bn_msg, key->size, sig, sig_len)); + CX_CHECK(cx_bn_mod_pow2(bn_r, bn_msg, key_d, key->size, bn_n)); + CX_CHECK(cx_bn_export(bn_r, sig, key->size)); + +end: + cx_bn_unlock(); + return error; } cx_err_t cx_rsa_sign_no_throw(const cx_rsa_private_key_t *key, - uint32_t mode, - cx_md_t hashID, - const uint8_t * hash, - size_t hash_len, - uint8_t * sig, - size_t sig_len) { - size_t output_hash_len = cx_pkcs1_get_hash_len(hashID); - return cx_rsa_sign_with_salt_len(key, mode, hashID, hash, hash_len, sig, sig_len, output_hash_len); + uint32_t mode, + cx_md_t hashID, + const uint8_t *hash, + size_t hash_len, + uint8_t *sig, + size_t sig_len) +{ + size_t output_hash_len = cx_pkcs1_get_hash_len(hashID); + return cx_rsa_sign_with_salt_len( + key, mode, hashID, hash, hash_len, sig, sig_len, output_hash_len); } bool cx_rsa_verify_with_salt_len(const cx_rsa_public_key_t *key, uint32_t mode, cx_md_t hashID, - const uint8_t * hash, + const uint8_t *hash, size_t hash_len, - uint8_t * sig, + uint8_t *sig, size_t sig_len, - size_t salt_len) { - size_t ok; - uint8_t *key_n; - uint8_t *key_e; - cx_bn_t bn_n, bn_msg, bn_r; - uint32_t nbits; - cx_err_t error; - - if (hash == NULL || hash_len > key->size) { - return false; - } - if (sig == NULL || sig_len != key->size) { - return false; - } - - ok = false; - - // decrypt sig - CX_CHECK(cx_rsa_get_public_components(key, &key_e, &key_n)); - CX_CHECK(cx_bn_lock(key->size, 0)); - CX_CHECK(cx_bn_alloc(&bn_r, key->size)); - CX_CHECK(cx_bn_alloc_init(&bn_n, key->size, key_n, key->size)); - CX_CHECK(cx_bn_alloc_init(&bn_msg, key->size, sig, sig_len)); - CX_CHECK(cx_bn_mod_pow2(bn_r, bn_msg, key_e, 4, bn_n)); - CX_CHECK(cx_bn_export(bn_r, sig, sig_len)); - - // verify sig - switch (mode & CX_MASK_PAD) { - case CX_PAD_PKCS1_1o5: - ok = cx_pkcs1_emsa_v1o5_verify(hashID, sig, sig_len, hash, hash_len); - break; - case CX_PAD_PKCS1_PSS: - CX_CHECK(cx_bn_cnt_bits(bn_n, &nbits)); - ok = cx_pkcs1_emsa_pss_verify_with_salt_len(hashID, sig, nbits - 1, hash, hash_len, salt_len); - break; - default: - error = CX_INVALID_PARAMETER; - goto end; - } - - end: - cx_bn_unlock(); - return error == CX_OK && ok; + size_t salt_len) +{ + size_t ok; + uint8_t *key_n; + uint8_t *key_e; + cx_bn_t bn_n, bn_msg, bn_r; + uint32_t nbits; + cx_err_t error; + + if (hash == NULL || hash_len > key->size) { + return false; + } + if (sig == NULL || sig_len != key->size) { + return false; + } + + ok = false; + + // decrypt sig + CX_CHECK(cx_rsa_get_public_components(key, &key_e, &key_n)); + CX_CHECK(cx_bn_lock(key->size, 0)); + CX_CHECK(cx_bn_alloc(&bn_r, key->size)); + CX_CHECK(cx_bn_alloc_init(&bn_n, key->size, key_n, key->size)); + CX_CHECK(cx_bn_alloc_init(&bn_msg, key->size, sig, sig_len)); + CX_CHECK(cx_bn_mod_pow2(bn_r, bn_msg, key_e, 4, bn_n)); + CX_CHECK(cx_bn_export(bn_r, sig, sig_len)); + + // verify sig + switch (mode & CX_MASK_PAD) { + case CX_PAD_PKCS1_1o5: + ok = cx_pkcs1_emsa_v1o5_verify(hashID, sig, sig_len, hash, hash_len); + break; + case CX_PAD_PKCS1_PSS: + CX_CHECK(cx_bn_cnt_bits(bn_n, &nbits)); + ok = cx_pkcs1_emsa_pss_verify_with_salt_len( + hashID, sig, nbits - 1, hash, hash_len, salt_len); + break; + default: + error = CX_INVALID_PARAMETER; + goto end; + } + +end: + cx_bn_unlock(); + return error == CX_OK && ok; } bool cx_rsa_verify(const cx_rsa_public_key_t *key, uint32_t mode, cx_md_t hashID, - const uint8_t * hash, + const uint8_t *hash, size_t hash_len, - uint8_t * sig, - size_t sig_len) { - size_t output_hash_len = cx_pkcs1_get_hash_len(hashID); - return cx_rsa_verify_with_salt_len(key, mode, hashID, hash, hash_len, sig, sig_len, output_hash_len); + uint8_t *sig, + size_t sig_len) +{ + size_t output_hash_len = cx_pkcs1_get_hash_len(hashID); + return cx_rsa_verify_with_salt_len( + key, mode, hashID, hash, hash_len, sig, sig_len, output_hash_len); } cx_err_t cx_rsa_encrypt_no_throw(const cx_rsa_public_key_t *key, - uint32_t mode, - cx_md_t hashID, - const uint8_t * mesg, - size_t mesg_len, - uint8_t * enc, - size_t enc_len) { - uint8_t *key_n; - uint8_t *key_e; - cx_bn_t bn_n, bn_msg, bn_r; - cx_err_t error; - - // cx_scc_struct_check_rsa_pubkey(key); - if (!(mesg && (mesg_len <= key->size))) { - return CX_INVALID_PARAMETER; - } - if (!(enc && (enc_len >= key->size))) { - return CX_INVALID_PARAMETER; - } - - // encode - switch (mode & CX_MASK_PAD) { - case CX_PAD_PKCS1_1o5: - enc_len = key->size; - CX_CHECK(cx_pkcs1_eme_v1o5_encode(hashID, enc, enc_len, mesg, mesg_len)); - break; - case CX_PAD_PKCS1_OAEP: - enc_len = key->size; - CX_CHECK(cx_pkcs1_eme_oaep_encode(hashID, enc, enc_len, mesg, mesg_len)); - break; - case CX_PAD_NONE: - memmove(enc, mesg, mesg_len); - enc_len = mesg_len; - break; - default: - error = CX_INVALID_PARAMETER; - goto end; - } - - // encrypt - CX_CHECK(cx_rsa_get_public_components(key, &key_e, &key_n)); - CX_CHECK(cx_bn_lock(key->size, 0)); - CX_CHECK(cx_bn_alloc(&bn_r, key->size)); - CX_CHECK(cx_bn_alloc_init(&bn_n, key->size, key_n, key->size)); - CX_CHECK(cx_bn_alloc_init(&bn_msg, key->size, enc, enc_len)); - CX_CHECK(cx_bn_mod_pow2(bn_r, bn_msg, key_e, 4, bn_n)); - CX_CHECK(cx_bn_export(bn_r, enc, key->size)); - - end: - cx_bn_unlock(); - return error; + uint32_t mode, + cx_md_t hashID, + const uint8_t *mesg, + size_t mesg_len, + uint8_t *enc, + size_t enc_len) +{ + uint8_t *key_n; + uint8_t *key_e; + cx_bn_t bn_n, bn_msg, bn_r; + cx_err_t error; + + // cx_scc_struct_check_rsa_pubkey(key); + if (!(mesg && (mesg_len <= key->size))) { + return CX_INVALID_PARAMETER; + } + if (!(enc && (enc_len >= key->size))) { + return CX_INVALID_PARAMETER; + } + + // encode + switch (mode & CX_MASK_PAD) { + case CX_PAD_PKCS1_1o5: + enc_len = key->size; + CX_CHECK(cx_pkcs1_eme_v1o5_encode(hashID, enc, enc_len, mesg, mesg_len)); + break; + case CX_PAD_PKCS1_OAEP: + enc_len = key->size; + CX_CHECK(cx_pkcs1_eme_oaep_encode(hashID, enc, enc_len, mesg, mesg_len)); + break; + case CX_PAD_NONE: + memmove(enc, mesg, mesg_len); + enc_len = mesg_len; + break; + default: + error = CX_INVALID_PARAMETER; + goto end; + } + + // encrypt + CX_CHECK(cx_rsa_get_public_components(key, &key_e, &key_n)); + CX_CHECK(cx_bn_lock(key->size, 0)); + CX_CHECK(cx_bn_alloc(&bn_r, key->size)); + CX_CHECK(cx_bn_alloc_init(&bn_n, key->size, key_n, key->size)); + CX_CHECK(cx_bn_alloc_init(&bn_msg, key->size, enc, enc_len)); + CX_CHECK(cx_bn_mod_pow2(bn_r, bn_msg, key_e, 4, bn_n)); + CX_CHECK(cx_bn_export(bn_r, enc, key->size)); + +end: + cx_bn_unlock(); + return error; } cx_err_t cx_rsa_decrypt_no_throw(const cx_rsa_private_key_t *key, - uint32_t mode, - cx_md_t hashID, - const uint8_t * mesg, - size_t mesg_len, - uint8_t * dec, - size_t * dec_len) { - uint8_t *key_n; - uint8_t *key_d; - cx_bn_t bn_n, bn_msg, bn_r; - cx_err_t error; - int diff; - - // cx_scc_struct_check_rsa_privkey(key); - if (!(mesg && (mesg_len == key->size))) { - return CX_INVALID_PARAMETER; - } - if (!(dec && (*dec_len >= key->size))) { - return CX_INVALID_PARAMETER; - } - - // decrypt - CX_CHECK(cx_rsa_get_private_components(key, &key_d, &key_n)); - CX_CHECK(cx_bn_lock(key->size, 0)); - CX_CHECK(cx_bn_alloc(&bn_r, key->size)); - CX_CHECK(cx_bn_alloc_init(&bn_n, key->size, key_n, key->size)); - CX_CHECK(cx_bn_alloc_init(&bn_msg, key->size, mesg, mesg_len)); - - // If the encrypted message is greater than the modulus, - // we consider the encrypted message as incorrect. - CX_CHECK(cx_bn_cmp(bn_msg, bn_n, &diff)); - if (diff > 0) { - error = CX_INVALID_PARAMETER; - goto end; - } - else { - CX_CHECK(cx_bn_mod_pow2(bn_r, bn_msg, key_d, key->size, bn_n)); - CX_CHECK(cx_bn_export(bn_r, dec, key->size)); - } - - switch (mode & CX_MASK_PAD) { - case CX_PAD_PKCS1_1o5: - *dec_len = cx_pkcs1_eme_v1o5_decode(hashID, dec, key->size, dec, *dec_len); - break; - case CX_PAD_PKCS1_OAEP: - CX_CHECK(cx_pkcs1_eme_oaep_decode(hashID, dec, key->size, dec, dec_len)); - break; - case CX_PAD_NONE: - *dec_len = key->size; - break; - default: - error = CX_INVALID_PARAMETER; - goto end; - } - - end: - cx_bn_unlock(); - return error; + uint32_t mode, + cx_md_t hashID, + const uint8_t *mesg, + size_t mesg_len, + uint8_t *dec, + size_t *dec_len) +{ + uint8_t *key_n; + uint8_t *key_d; + cx_bn_t bn_n, bn_msg, bn_r; + cx_err_t error; + int diff; + + // cx_scc_struct_check_rsa_privkey(key); + if (!(mesg && (mesg_len == key->size))) { + return CX_INVALID_PARAMETER; + } + if (!(dec && (*dec_len >= key->size))) { + return CX_INVALID_PARAMETER; + } + + // decrypt + CX_CHECK(cx_rsa_get_private_components(key, &key_d, &key_n)); + CX_CHECK(cx_bn_lock(key->size, 0)); + CX_CHECK(cx_bn_alloc(&bn_r, key->size)); + CX_CHECK(cx_bn_alloc_init(&bn_n, key->size, key_n, key->size)); + CX_CHECK(cx_bn_alloc_init(&bn_msg, key->size, mesg, mesg_len)); + + // If the encrypted message is greater than the modulus, + // we consider the encrypted message as incorrect. + CX_CHECK(cx_bn_cmp(bn_msg, bn_n, &diff)); + if (diff > 0) { + error = CX_INVALID_PARAMETER; + goto end; + } + else { + CX_CHECK(cx_bn_mod_pow2(bn_r, bn_msg, key_d, key->size, bn_n)); + CX_CHECK(cx_bn_export(bn_r, dec, key->size)); + } + + switch (mode & CX_MASK_PAD) { + case CX_PAD_PKCS1_1o5: + *dec_len = cx_pkcs1_eme_v1o5_decode(hashID, dec, key->size, dec, *dec_len); + break; + case CX_PAD_PKCS1_OAEP: + CX_CHECK(cx_pkcs1_eme_oaep_decode(hashID, dec, key->size, dec, dec_len)); + break; + case CX_PAD_NONE: + *dec_len = key->size; + break; + default: + error = CX_INVALID_PARAMETER; + goto end; + } + +end: + cx_bn_unlock(); + return error; } #pragma GCC diagnostic pop -#endif // HAVE_RSA +#endif // HAVE_RSA diff --git a/lib_cxng/src/cx_rsa.h b/lib_cxng/src/cx_rsa.h index a94695b60..30365d15c 100644 --- a/lib_cxng/src/cx_rsa.h +++ b/lib_cxng/src/cx_rsa.h @@ -1,20 +1,20 @@ /******************************************************************************* -* Ledger Nano S - Secure firmware -* (c) 2022 Ledger -* -* Licensed under the Apache License, Version 2.0 (the "License"); -* you may not use this file except in compliance with the License. -* You may obtain a copy of the License at -* -* http://www.apache.org/licenses/LICENSE-2.0 -* -* Unless required by applicable law or agreed to in writing, software -* distributed under the License is distributed on an "AS IS" BASIS, -* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -* See the License for the specific language governing permissions and -* limitations under the License. -********************************************************************************/ + * Ledger Nano S - Secure firmware + * (c) 2022 Ledger + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + ********************************************************************************/ #ifdef HAVE_RSA @@ -40,7 +40,11 @@ size_t cx_pkcs1_get_hash_len(cx_md_t hID); * * @return em_len, if encoded 0 else */ -cx_err_t cx_pkcs1_emsa_v1o5_encode(cx_md_t hID, uint8_t *em, size_t em_len, const uint8_t *mHash, size_t mHashLen); +cx_err_t cx_pkcs1_emsa_v1o5_encode(cx_md_t hID, + uint8_t *em, + size_t em_len, + const uint8_t *mHash, + size_t mHashLen); /* * @param [in] hID underlaid hash (ignored, sha256 forced) * @param [in] em encoded message to verify @@ -50,7 +54,11 @@ cx_err_t cx_pkcs1_emsa_v1o5_encode(cx_md_t hID, uint8_t *em, size_t em_len, cons * * @return 1 if verifed, 0 else */ -bool cx_pkcs1_emsa_v1o5_verify(cx_md_t hID, uint8_t *em, size_t em_len, const uint8_t *mHash, size_t mHashLen); +bool cx_pkcs1_emsa_v1o5_verify(cx_md_t hID, + uint8_t *em, + size_t em_len, + const uint8_t *mHash, + size_t mHashLen); /* The salt length is equal to the mHashLen value. * If another salt length is to be used, the @@ -65,7 +73,12 @@ bool cx_pkcs1_emsa_v1o5_verify(cx_md_t hID, uint8_t *em, size_t em_len, const ui * * @return em_len, if encoded 0 else */ -cx_err_t cx_pkcs1_emsa_pss_encode(cx_md_t hID, uint8_t *em, size_t em_len, const uint8_t *mHash, size_t mHashLen, size_t *size); +cx_err_t cx_pkcs1_emsa_pss_encode(cx_md_t hID, + uint8_t *em, + size_t em_len, + const uint8_t *mHash, + size_t mHashLen, + size_t *size); /* * @param [in] hID underlaid hash (ignored, sha256 forced) @@ -77,7 +90,13 @@ cx_err_t cx_pkcs1_emsa_pss_encode(cx_md_t hID, uint8_t *em, size_t em_len, const * * @return em_len, if encoded 0 else */ -cx_err_t cx_pkcs1_emsa_pss_encode_with_salt_len(cx_md_t hID, uint8_t *em, size_t em_len, const uint8_t *mHash, size_t mHashLen, size_t mSaltLen, size_t *size); +cx_err_t cx_pkcs1_emsa_pss_encode_with_salt_len(cx_md_t hID, + uint8_t *em, + size_t em_len, + const uint8_t *mHash, + size_t mHashLen, + size_t mSaltLen, + size_t *size); /* The salt length is equal to the mHashLen value. * If another salt length is to be used, the @@ -91,7 +110,11 @@ cx_err_t cx_pkcs1_emsa_pss_encode_with_salt_len(cx_md_t hID, uint8_t *em, size_t * * @return 1 if verifed, 0 else */ -bool cx_pkcs1_emsa_pss_verify(cx_md_t hID, uint8_t *em, size_t em_len, const uint8_t *mHash, size_t mHashLen); +bool cx_pkcs1_emsa_pss_verify(cx_md_t hID, + uint8_t *em, + size_t em_len, + const uint8_t *mHash, + size_t mHashLen); /* * @param [in] hID underlaid hash @@ -103,7 +126,12 @@ bool cx_pkcs1_emsa_pss_verify(cx_md_t hID, uint8_t *em, size_t em_len, const uin * * @return 1 if verifed, 0 else */ -bool cx_pkcs1_emsa_pss_verify_with_salt_len(cx_md_t hID, uint8_t *em, size_t em_len, const uint8_t *mHash, size_t mHashLen, size_t mSaltLen); +bool cx_pkcs1_emsa_pss_verify_with_salt_len(cx_md_t hID, + uint8_t *em, + size_t em_len, + const uint8_t *mHash, + size_t mHashLen, + size_t mSaltLen); /* * @param [in] hID underlaid hash (ignored, sha256 forced) @@ -114,7 +142,11 @@ bool cx_pkcs1_emsa_pss_verify_with_salt_len(cx_md_t hID, uint8_t *em, size_t em_ * * @return em_len, if encoded 0 else */ -cx_err_t cx_pkcs1_eme_v1o5_encode(cx_md_t hID, uint8_t *em, size_t em_len, const uint8_t *mHash, size_t mHashLen); +cx_err_t cx_pkcs1_eme_v1o5_encode(cx_md_t hID, + uint8_t *em, + size_t em_len, + const uint8_t *mHash, + size_t mHashLen); /* * @param [in] hID underlaid hash (ignored, sha256 forced) * @param [in] em encoded message @@ -124,7 +156,11 @@ cx_err_t cx_pkcs1_eme_v1o5_encode(cx_md_t hID, uint8_t *em, size_t em_len, const * * @return decoded message length, -1 if decoding fail */ -size_t cx_pkcs1_eme_v1o5_decode(cx_md_t hID, uint8_t *em, size_t em_len, uint8_t *mHash, size_t mHashLen); +size_t cx_pkcs1_eme_v1o5_decode(cx_md_t hID, + uint8_t *em, + size_t em_len, + uint8_t *mHash, + size_t mHashLen); /* * @param [in] hID underlaid hash (ignored, sha256 forced) @@ -135,7 +171,11 @@ size_t cx_pkcs1_eme_v1o5_decode(cx_md_t hID, uint8_t *em, size_t em_len, uint8_t * * @return em_len, if encoded 0 else */ -cx_err_t cx_pkcs1_eme_oaep_encode(cx_md_t hID, uint8_t *em, size_t em_len, const uint8_t *m, size_t mLen); +cx_err_t cx_pkcs1_eme_oaep_encode(cx_md_t hID, + uint8_t *em, + size_t em_len, + const uint8_t *m, + size_t mLen); /* * @param [in] hID underlaid hash (ignored, sha256 forced) * @param [in] em encoded message @@ -145,59 +185,63 @@ cx_err_t cx_pkcs1_eme_oaep_encode(cx_md_t hID, uint8_t *em, size_t em_len, const * * @return decoded message length, -1 if decoding fail */ -cx_err_t cx_pkcs1_eme_oaep_decode(cx_md_t hID, uint8_t *em, size_t em_len, uint8_t *m, size_t *mLen); +cx_err_t cx_pkcs1_eme_oaep_decode(cx_md_t hID, + uint8_t *em, + size_t em_len, + uint8_t *m, + size_t *mLen); // For PKCS1.5 -#define PKCS1_DIGEST_BUFFER_LENGTH 64 +#define PKCS1_DIGEST_BUFFER_LENGTH 64 struct cx_pkcs1_s { union { - cx_hash_t hash; + cx_hash_t hash; #if defined(HAVE_SHA256) cx_sha256_t sha256; -#endif // HAVE_SHA256 +#endif // HAVE_SHA256 #if defined(HAVE_SHA512) cx_sha512_t sha512; -#endif // HAVE_SHA512 +#endif // HAVE_SHA512 } hash_ctx; - uint8_t digest[PKCS1_DIGEST_BUFFER_LENGTH]; - uint8_t MGF1[512]; + uint8_t digest[PKCS1_DIGEST_BUFFER_LENGTH]; + uint8_t MGF1[512]; }; -typedef struct cx_pkcs1_s cx_pkcs1_t; +typedef struct cx_pkcs1_s cx_pkcs1_t; #if defined(HAVE_SHA224) -#define CX_OID_SHA224_LENGTH 19 +#define CX_OID_SHA224_LENGTH 19 extern uint8_t const C_cx_oid_sha224[CX_OID_SHA224_LENGTH]; -#endif // HAVE_SHA224 +#endif // HAVE_SHA224 #if defined(HAVE_SHA256) -#define CX_OID_SHA256_LENGTH 19 +#define CX_OID_SHA256_LENGTH 19 extern uint8_t const C_cx_oid_sha256[CX_OID_SHA256_LENGTH]; -#endif // HAVE_SHA256 +#endif // HAVE_SHA256 #if defined(HAVE_SHA384) -#define CX_OID_SHA384_LENGTH 19 +#define CX_OID_SHA384_LENGTH 19 extern uint8_t const C_cx_oid_sha384[CX_OID_SHA384_LENGTH]; -#endif // HAVE_SHA384 +#endif // HAVE_SHA384 #if defined(HAVE_SHA512) -#define CX_OID_SHA512_LENGTH 19 +#define CX_OID_SHA512_LENGTH 19 extern uint8_t const C_cx_oid_sha512[CX_OID_SHA512_LENGTH]; -#endif // HAVE_SHA512 +#endif // HAVE_SHA512 #if defined(HAVE_SHA3) -#define CX_OID_SHA3_256_LENGTH 19 +#define CX_OID_SHA3_256_LENGTH 19 extern uint8_t const C_cx_oid_sha3_256[CX_OID_SHA3_256_LENGTH]; -#define CX_OID_SHA3_512_LENGTH 19 +#define CX_OID_SHA3_512_LENGTH 19 extern uint8_t const C_cx_oid_sha3_512[CX_OID_SHA3_512_LENGTH]; -#endif // HAVE_SHA3 +#endif // HAVE_SHA3 cx_err_t cx_rsa_get_public_components(const cx_rsa_public_key_t *key, uint8_t **e, uint8_t **n); cx_err_t cx_rsa_get_private_components(const cx_rsa_private_key_t *key, uint8_t **d, uint8_t **n); cx_err_t cx_rsa_private_key_ctx_size(const cx_rsa_private_key_t *key, size_t *size); -#endif // CX_RSA_H -#endif // HAVE_RSA +#endif // CX_RSA_H +#endif // HAVE_RSA diff --git a/lib_cxng/src/cx_selftests.c b/lib_cxng/src/cx_selftests.c index f7d72ba56..40babea3f 100644 --- a/lib_cxng/src/cx_selftests.c +++ b/lib_cxng/src/cx_selftests.c @@ -1,20 +1,20 @@ /******************************************************************************* -* Ledger Nano S - Secure firmware -* (c) 2022 Ledger -* -* Licensed under the Apache License, Version 2.0 (the "License"); -* you may not use this file except in compliance with the License. -* You may obtain a copy of the License at -* -* http://www.apache.org/licenses/LICENSE-2.0 -* -* Unless required by applicable law or agreed to in writing, software -* distributed under the License is distributed on an "AS IS" BASIS, -* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -* See the License for the specific language governing permissions and -* limitations under the License. -********************************************************************************/ + * Ledger Nano S - Secure firmware + * (c) 2022 Ledger + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + ********************************************************************************/ #ifdef HAVE_SELFTESTS @@ -25,56 +25,56 @@ #include "cx_ram.h" enum test_id { - CX_TEST_MATHM_ID, + CX_TEST_MATHM_ID, - CX_TEST_AES_ID, + CX_TEST_AES_ID, - CX_TEST_RIPEMD160_ID, - CX_TEST_SHA224_ID, - CX_TEST_SHA256_ID, - CX_TEST_SHA384_ID, - CX_TEST_SHA512_ID, + CX_TEST_RIPEMD160_ID, + CX_TEST_SHA224_ID, + CX_TEST_SHA256_ID, + CX_TEST_SHA384_ID, + CX_TEST_SHA512_ID, - CX_TEST_SHA3_ID, - CX_TEST_SHA3_XOF_ID, + CX_TEST_SHA3_ID, + CX_TEST_SHA3_XOF_ID, - CX_TEST_BLAKE2B_ID, - CX_TEST_GROESTL_ID, + CX_TEST_BLAKE2B_ID, + CX_TEST_GROESTL_ID, - CX_TEST_HMAC_RIPEMD160_ID, - CX_TEST_HMAC_SHA256_ID, - CX_TEST_HMAC_SHA512_ID, - CX_TEST_PBKDF2_ID, + CX_TEST_HMAC_RIPEMD160_ID, + CX_TEST_HMAC_SHA256_ID, + CX_TEST_HMAC_SHA512_ID, + CX_TEST_PBKDF2_ID, - CX_TEST_ECDSA_ID, - CX_TEST_ECDSA_RFC6979_ID, + CX_TEST_ECDSA_ID, + CX_TEST_ECDSA_RFC6979_ID, - CX_TEST_EDDSA_ID, + CX_TEST_EDDSA_ID, - CX_TEST_ECSCHNORR_ID, + CX_TEST_ECSCHNORR_ID, - CX_TEST_BORROMEAN_ID, + CX_TEST_BORROMEAN_ID, - CX_TEST_ECFP_ADD_ID, + CX_TEST_ECFP_ADD_ID, - CX_TEST_EC_KEYGEN_ID, + CX_TEST_EC_KEYGEN_ID, - CX_TEST_ECDH_ID, + CX_TEST_ECDH_ID, - CX_TEST_RSA_ID, + CX_TEST_RSA_ID, - // how many - CX_TEST_COUNT, + // how many + CX_TEST_COUNT, }; typedef struct cx_selftest_s { - uint8_t _in[512]; - uint8_t _out[512]; - int _cx_failure_counter; - int _cx_results[CX_TEST_COUNT]; + uint8_t _in[512]; + uint8_t _out[512]; + int _cx_failure_counter; + int _cx_results[CX_TEST_COUNT]; } cx_selftest_t; -#define G_HAVE_SELFTESTS ((cx_selftest_t*)0x0020000800) +#define G_HAVE_SELFTESTS ((cx_selftest_t *) 0x0020000800) #define IN G_HAVE_SELFTESTS->_in #define OUT G_HAVE_SELFTESTS->_out #define cx_failure_counter G_HAVE_SELFTESTS->_cx_failure_counter @@ -84,76 +84,60 @@ void cx_bm_setup(); void cx_bm_start(); void cx_bm_stop(); -void cx_printa(char *prefix, const unsigned char *r, unsigned short len) { - UNUSED(prefix); - cx_printf((" %s %.4d ", prefix, len)); - while (len--) { - cx_printf(("%.2x", *r)); - r++; - } - cx_printf(("\n")); +void cx_printa(char *prefix, const unsigned char *r, unsigned short len) +{ + UNUSED(prefix); + cx_printf((" %s %.4d ", prefix, len)); + while (len--) { + cx_printf(("%.2x", *r)); + r++; + } + cx_printf(("\n")); } - #ifdef ST31 #include "product.h" #endif -int cx_st_onefail(void) { - volatile int i = 1; // avoid inline - // breaker - return i; +int cx_st_onefail(void) +{ + volatile int i = 1; // avoid inline + // breaker + return i; } -int cx_break(void) { - volatile int i = 2; // avoid inline - // breaker - return i; +int cx_break(void) +{ + volatile int i = 2; // avoid inline + // breaker + return i; } -void cx_st_check_result(int r, int ID, int c) { - if (r) { - cx_results[ID] |= 1 << c; - cx_failure_counter++; - cx_st_onefail(); - } +void cx_st_check_result(int r, int ID, int c) +{ + if (r) { + cx_results[ID] |= 1 << c; + cx_failure_counter++; + cx_st_onefail(); + } } /* ======================================================================= */ /* RAM BUFF */ /* ======================================================================= */ -static void cx_clr_inout(void) { - memset(IN, 0, sizeof(IN)); - memset(OUT, 0, sizeof(OUT)); +static void cx_clr_inout(void) +{ + memset(IN, 0, sizeof(IN)); + memset(OUT, 0, sizeof(OUT)); } /* ======================================================================= */ /* RAND */ /* ======================================================================= */ - - - - - - - - - - - - - - - - - - - - - /* -*************************************** 1 skip 0 ********************************************************* +*************************************** 1 skip 0 +********************************************************* --------REF-------- order fffffffffffffffffffffffffffffffffffffffffffffffffffffffefffffc2f secexp c48b5c4c5b2ae33df94192f6269d55921fb0f095be4d843b507a2a716954eea7 @@ -181,17 +165,18 @@ ref b2i/ ret b22ac3d26ff3734315f18c9662e7c7d8e84a1e83a6d9c77766e6e149a53c584f => b22ac3d26ff3734315f18c9662e7c7d8e84a1e83a6d9c77766e6e149a53c584f */ static const unsigned char rfc6979_sha256_order1[] = { - 0xff, 0xff, 0xff, 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, 0xfc, 0x2f -}; + 0xff, 0xff, 0xff, 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, 0xfc, 0x2f}; static const unsigned char rfc6979_sha256_key1[] = { - 0xc4, 0x8b, 0x5c, 0x4c, 0x5b, 0x2a, 0xe3, 0x3d, 0xf9, 0x41, 0x92, 0xf6, 0x26, 0x9d, 0x55, 0x92, 0x1f, 0xb0, 0xf0, 0x95, 0xbe, 0x4d, 0x84, 0x3b, 0x50, 0x7a, 0x2a, 0x71, 0x69, 0x54, 0xee, 0xa7 -}; + 0xc4, 0x8b, 0x5c, 0x4c, 0x5b, 0x2a, 0xe3, 0x3d, 0xf9, 0x41, 0x92, 0xf6, 0x26, 0x9d, 0x55, 0x92, + 0x1f, 0xb0, 0xf0, 0x95, 0xbe, 0x4d, 0x84, 0x3b, 0x50, 0x7a, 0x2a, 0x71, 0x69, 0x54, 0xee, 0xa7}; static const unsigned char rfc6979_sha256_hash1[] = { - 0xef, 0x84, 0xda, 0xe8, 0xcb, 0x46, 0x95, 0x13, 0x14, 0x92, 0x05, 0x00, 0xec, 0x18, 0xa3, 0x86, 0x70, 0xcd, 0xa4, 0x37, 0xb4, 0x5c, 0x7a, 0xea, 0xa7, 0x36, 0x62, 0x16, 0x66, 0x38, 0xf7, 0x4d -}; + 0xef, 0x84, 0xda, 0xe8, 0xcb, 0x46, 0x95, 0x13, 0x14, 0x92, 0x05, 0x00, 0xec, 0x18, 0xa3, 0x86, + 0x70, 0xcd, 0xa4, 0x37, 0xb4, 0x5c, 0x7a, 0xea, 0xa7, 0x36, 0x62, 0x16, 0x66, 0x38, 0xf7, 0x4d}; /* -*************************************** 2 skip 0 ********************************************************* +*************************************** 2 skip 0 +********************************************************* --------REF-------- order 0800000000000011000000000000000000000000000000000000000000000001 secexp 3f8311eece8cafea3bf568aa90457ad6bbc47deed0e3c44e0aa94b98ac41f @@ -225,45 +210,50 @@ ref b2i/ shift by 4 */ static const unsigned char rfc6979_sha256_order2[] = { - 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x11, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01 -}; + 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x11, 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 rfc6979_sha256_key2[] = { - 0x00, 0x03, 0xf8, 0x31, 0x1e, 0xec, 0xe8, 0xca, 0xfe, 0xa3, 0xbf, 0x56, 0x8a, 0xa9, 0x04, 0x57, 0xad, 0x6b, 0xbc, 0x47, 0xde, 0xed, 0x0e, 0x3c, 0x44, 0xe0, 0xaa, 0x94, 0xb9, 0x8a, 0xc4, 0x1f -}; + 0x00, 0x03, 0xf8, 0x31, 0x1e, 0xec, 0xe8, 0xca, 0xfe, 0xa3, 0xbf, 0x56, 0x8a, 0xa9, 0x04, 0x57, + 0xad, 0x6b, 0xbc, 0x47, 0xde, 0xed, 0x0e, 0x3c, 0x44, 0xe0, 0xaa, 0x94, 0xb9, 0x8a, 0xc4, 0x1f}; static const unsigned char rfc6979_sha256_hash2[] = { - 0xe5, 0x11, 0xc5, 0x43, 0x2e, 0xa4, 0xf8, 0x0a, 0xa4, 0x34, 0xb8, 0x42, 0xfe, 0x53, 0x98, 0xec, 0x23, 0xd6, 0x2f, 0x3e, 0x0d, 0xa0, 0x6c, 0x24, 0x00, 0x00, 0x5e, 0xf9, 0xc7, 0xac, 0x1b, 0x4b -}; - - -void cx_st_rfc6979() { - - cx_rng_rfc6979(CX_SHA256, - rfc6979_sha256_key1, sizeof(rfc6979_sha256_key1), - rfc6979_sha256_hash1, sizeof(rfc6979_sha256_hash1), - rfc6979_sha256_order1, sizeof(rfc6979_sha256_order1), - OUT, sizeof(rfc6979_sha256_order1)); - - cx_rng_rfc6979(CX_SHA256, - rfc6979_sha256_key2, sizeof(rfc6979_sha256_key2), - rfc6979_sha256_hash2, sizeof(rfc6979_sha256_hash2), - rfc6979_sha256_order2, sizeof(rfc6979_sha256_order2), - OUT, sizeof(rfc6979_sha256_order1)); - + 0xe5, 0x11, 0xc5, 0x43, 0x2e, 0xa4, 0xf8, 0x0a, 0xa4, 0x34, 0xb8, 0x42, 0xfe, 0x53, 0x98, 0xec, + 0x23, 0xd6, 0x2f, 0x3e, 0x0d, 0xa0, 0x6c, 0x24, 0x00, 0x00, 0x5e, 0xf9, 0xc7, 0xac, 0x1b, 0x4b}; + +void cx_st_rfc6979() +{ + cx_rng_rfc6979(CX_SHA256, + rfc6979_sha256_key1, + sizeof(rfc6979_sha256_key1), + rfc6979_sha256_hash1, + sizeof(rfc6979_sha256_hash1), + rfc6979_sha256_order1, + sizeof(rfc6979_sha256_order1), + OUT, + sizeof(rfc6979_sha256_order1)); + + cx_rng_rfc6979(CX_SHA256, + rfc6979_sha256_key2, + sizeof(rfc6979_sha256_key2), + rfc6979_sha256_hash2, + sizeof(rfc6979_sha256_hash2), + rfc6979_sha256_order2, + sizeof(rfc6979_sha256_order2), + OUT, + sizeof(rfc6979_sha256_order1)); } - - // ===================================================================================== +int cx_selftest() +{ + int volatile looper = HAVE_SELFTESTS_START_LOOP; + while (looper) + ; + memset(G_HAVE_SELFTESTS, 0, sizeof(cx_selftest_t)); + cx_st_rfc6979(); -int cx_selftest() { - int volatile looper = HAVE_SELFTESTS_START_LOOP; - while (looper); - memset(G_HAVE_SELFTESTS, 0, sizeof(cx_selftest_t)); - cx_st_rfc6979(); - - cx_break(); - return cx_failure_counter; - } + cx_break(); + return cx_failure_counter; +} -#endif // SELFTEST +#endif // SELFTEST diff --git a/lib_cxng/src/cx_selftests.h b/lib_cxng/src/cx_selftests.h index 32c218cd2..312399ee0 100644 --- a/lib_cxng/src/cx_selftests.h +++ b/lib_cxng/src/cx_selftests.h @@ -1,20 +1,20 @@ /******************************************************************************* -* Ledger Nano S - Secure firmware -* (c) 2022 Ledger -* -* Licensed under the Apache License, Version 2.0 (the "License"); -* you may not use this file except in compliance with the License. -* You may obtain a copy of the License at -* -* http://www.apache.org/licenses/LICENSE-2.0 -* -* Unless required by applicable law or agreed to in writing, software -* distributed under the License is distributed on an "AS IS" BASIS, -* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -* See the License for the specific language governing permissions and -* limitations under the License. -********************************************************************************/ + * Ledger Nano S - Secure firmware + * (c) 2022 Ledger + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT 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 HAVE_SELFTESTS_H #define HAVE_SELFTESTS_H @@ -37,6 +37,6 @@ void cx_check_result(int r); int cx_benchmark(void); -#endif // HAVE_SELFTESTS +#endif // HAVE_SELFTESTS -#endif // HAVE_SELFTESTS_H +#endif // HAVE_SELFTESTS_H diff --git a/lib_cxng/src/cx_sha256.c b/lib_cxng/src/cx_sha256.c index 2d23a17fe..446dc4535 100644 --- a/lib_cxng/src/cx_sha256.c +++ b/lib_cxng/src/cx_sha256.c @@ -1,20 +1,20 @@ /******************************************************************************* -* Ledger Nano S - Secure firmware -* (c) 2022 Ledger -* -* Licensed under the Apache License, Version 2.0 (the "License"); -* you may not use this file except in compliance with the License. -* You may obtain a copy of the License at -* -* http://www.apache.org/licenses/LICENSE-2.0 -* -* Unless required by applicable law or agreed to in writing, software -* distributed under the License is distributed on an "AS IS" BASIS, -* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -* See the License for the specific language governing permissions and -* limitations under the License. -********************************************************************************/ + * Ledger Nano S - Secure firmware + * (c) 2022 Ledger + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT 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(HAVE_SHA256) || defined(HAVE_SHA224) @@ -26,32 +26,30 @@ #include #ifdef HAVE_SHA224 -const cx_hash_info_t cx_sha224_info = { - CX_SHA224, - CX_SHA224_SIZE, - SHA256_BLOCK_SIZE, - sizeof(cx_sha256_t), - (cx_err_t(*)(cx_hash_t *ctx))cx_sha224_init_no_throw, - (cx_err_t (*)(cx_hash_t *ctx, const uint8_t *data, size_t len))cx_sha256_update, - (cx_err_t (*)(cx_hash_t *ctx, uint8_t *digest))cx_sha256_final, - NULL, - NULL -}; -#endif // HAVE_SHA224 +const cx_hash_info_t cx_sha224_info + = {CX_SHA224, + CX_SHA224_SIZE, + SHA256_BLOCK_SIZE, + sizeof(cx_sha256_t), + (cx_err_t(*)(cx_hash_t * ctx)) cx_sha224_init_no_throw, + (cx_err_t(*)(cx_hash_t * ctx, const uint8_t *data, size_t len)) cx_sha256_update, + (cx_err_t(*)(cx_hash_t * ctx, uint8_t *digest)) cx_sha256_final, + NULL, + NULL}; +#endif // HAVE_SHA224 #ifdef HAVE_SHA256 -const cx_hash_info_t cx_sha256_info = { - CX_SHA256, - CX_SHA256_SIZE, - SHA256_BLOCK_SIZE, - sizeof(cx_sha256_t), - (cx_err_t (*)(cx_hash_t *ctx))cx_sha256_init_no_throw, - (cx_err_t (*)(cx_hash_t *ctx, const uint8_t *data, size_t len))cx_sha256_update, - (cx_err_t (*)(cx_hash_t *ctx, uint8_t *digest))cx_sha256_final, - NULL, - NULL -}; -#endif // HAVE_SHA256 +const cx_hash_info_t cx_sha256_info + = {CX_SHA256, + CX_SHA256_SIZE, + SHA256_BLOCK_SIZE, + sizeof(cx_sha256_t), + (cx_err_t(*)(cx_hash_t * ctx)) cx_sha256_init_no_throw, + (cx_err_t(*)(cx_hash_t * ctx, const uint8_t *data, size_t len)) cx_sha256_update, + (cx_err_t(*)(cx_hash_t * ctx, uint8_t *digest)) cx_sha256_final, + NULL, + NULL}; +#endif // HAVE_SHA256 static const uint32_t primeSqrt[] = { 0x428a2f98, 0x71374491, 0xb5c0fbcf, 0xe9b5dba5, 0x3956c25b, 0x59f111f1, 0x923f82a4, 0xab1c5ed5, @@ -65,50 +63,64 @@ static const uint32_t primeSqrt[] = { }; #if defined(HAVE_SHA224) -static const uint32_t hzero_224[] = {0xc1059ed8, 0x367cd507, 0x3070dd17, 0xf70e5939, - 0xffc00b31, 0x68581511, 0x64f98fa7, 0xbefa4fa4}; +static const uint32_t hzero_224[] = {0xc1059ed8, + 0x367cd507, + 0x3070dd17, + 0xf70e5939, + 0xffc00b31, + 0x68581511, + 0x64f98fa7, + 0xbefa4fa4}; #endif -static const uint32_t hzero[] = {0x6a09e667, 0xbb67ae85, 0x3c6ef372, 0xa54ff53a, - 0x510e527f, 0x9b05688c, 0x1f83d9ab, 0x5be0cd19}; - +static const uint32_t hzero[] = {0x6a09e667, + 0xbb67ae85, + 0x3c6ef372, + 0xa54ff53a, + 0x510e527f, + 0x9b05688c, + 0x1f83d9ab, + 0x5be0cd19}; #define sig256(x, a, b, c) (cx_rotr((x), a) ^ cx_rotr((x), b) ^ cx_shr((x), c)) #define sum256(x, a, b, c) (cx_rotr((x), a) ^ cx_rotr((x), b) ^ cx_rotr((x), c)) #define sigma0(x) sig256(x, 7, 18, 3) #define sigma1(x) sig256(x, 17, 19, 10) -#define sum0(x) sum256(x, 2, 13, 22) -#define sum1(x) sum256(x, 6, 11, 25) +#define sum0(x) sum256(x, 2, 13, 22) +#define sum1(x) sum256(x, 6, 11, 25) // #define ch(x, y, z) (((x) & (y)) ^ (~(x) & (z))) // #define maj(x, y, z) (((x) & (y)) ^ ((x) & (z)) ^ ((y) & (z))) -#define ch(x, y, z) (z ^ (x & (y ^ z))) +#define ch(x, y, z) (z ^ (x & (y ^ z))) #define maj(x, y, z) ((x & y) | (z & (x | y))) #if defined(HAVE_SHA224) -cx_err_t cx_sha224_init_no_throw(cx_sha256_t *hash) { - memset(hash, 0, sizeof(cx_sha256_t)); - hash->header.info = &cx_sha224_info; - memmove(hash->acc, hzero_224, sizeof(hzero)); - return CX_OK; +cx_err_t cx_sha224_init_no_throw(cx_sha256_t *hash) +{ + memset(hash, 0, sizeof(cx_sha256_t)); + hash->header.info = &cx_sha224_info; + memmove(hash->acc, hzero_224, sizeof(hzero)); + return CX_OK; } #endif -cx_err_t cx_sha256_init_no_throw(cx_sha256_t *hash) { - memset(hash, 0, sizeof(cx_sha256_t)); - hash->header.info = &cx_sha256_info; - memmove(hash->acc, hzero, sizeof(hzero)); - return CX_OK; +cx_err_t cx_sha256_init_no_throw(cx_sha256_t *hash) +{ + memset(hash, 0, sizeof(cx_sha256_t)); + hash->header.info = &cx_sha256_info; + memmove(hash->acc, hzero, sizeof(hzero)); + return CX_OK; } -static void cx_sha256_block(cx_sha256_t *hash) { - uint32_t t1, t2; +static void cx_sha256_block(cx_sha256_t *hash) +{ + uint32_t t1, t2; - uint32_t ACC[8]; - uint32_t *accumulator; - uint32_t *X; + uint32_t ACC[8]; + uint32_t *accumulator; + uint32_t *X; #define A ACC[0] #define B ACC[1] @@ -119,156 +131,161 @@ static void cx_sha256_block(cx_sha256_t *hash) { #define G ACC[6] #define H ACC[7] - // init - X = ((uint32_t *)&hash->block[0]); - accumulator = (uint32_t *)&hash->acc[0]; - memmove(ACC, accumulator, sizeof(ACC)); + // init + X = ((uint32_t *) &hash->block[0]); + accumulator = (uint32_t *) &hash->acc[0]; + memmove(ACC, accumulator, sizeof(ACC)); #ifdef ARCH_LITTLE_ENDIAN - cx_swap_buffer32(X, 16); + cx_swap_buffer32(X, 16); #endif - /* - * T1 = Sum_1_256(e) + Chg(e,f,g) + K_t_256 + Wt - * T2 = Sum_0_256(a) + Maj(abc) - * h = g ; - * g = f; - * f = e; - * e = d + T1; - * d = c; - * c = b; - * b = a; - * a = T1 + T2; - */ - for (int j = 0; j < 64; j++) { - /* for j in 16 to 63, Xj <- (Sigma_1_256( Xj-2) + Xj-7 + Sigma_0_256(Xj-15) - * + Xj-16 ). */ - if (j >= 16) { - X[j & 0xF] = (sigma1(X[(j - 2) & 0xF]) + X[(j - 7) & 0xF] + sigma0(X[(j - 15) & 0xF]) + X[(j - 16) & 0xF]); + /* + * T1 = Sum_1_256(e) + Chg(e,f,g) + K_t_256 + Wt + * T2 = Sum_0_256(a) + Maj(abc) + * h = g ; + * g = f; + * f = e; + * e = d + T1; + * d = c; + * c = b; + * b = a; + * a = T1 + T2; + */ + for (int j = 0; j < 64; j++) { + /* for j in 16 to 63, Xj <- (Sigma_1_256( Xj-2) + Xj-7 + Sigma_0_256(Xj-15) + * + Xj-16 ). */ + if (j >= 16) { + X[j & 0xF] = (sigma1(X[(j - 2) & 0xF]) + X[(j - 7) & 0xF] + sigma0(X[(j - 15) & 0xF]) + + X[(j - 16) & 0xF]); + } + + t1 = H + sum1(E) + ch(E, F, G) + primeSqrt[j] + X[j & 0xF]; + t2 = sum0(A) + maj(A, B, C); + /* + H = G ; + G = F; + F = E; + E = D+t1; + D = C; + C = B; + B = A; + A = t1+t2; + */ + memmove(&ACC[1], &ACC[0], sizeof(ACC) - sizeof(uint32_t)); + E += t1; + A = t1 + t2; } - t1 = H + sum1(E) + ch(E, F, G) + primeSqrt[j] + X[j & 0xF]; - t2 = sum0(A) + maj(A, B, C); - /* - H = G ; - G = F; - F = E; - E = D+t1; - D = C; - C = B; - B = A; - A = t1+t2; - */ - memmove(&ACC[1], &ACC[0], sizeof(ACC) - sizeof(uint32_t)); - E += t1; - A = t1 + t2; - } - - //(update chaining values) (H1 , H2 , H3 , H4 ) <- (H1 + A, H2 + B, H3 + C, H4 - //+ D...) - accumulator[0] += A; - accumulator[1] += B; - accumulator[2] += C; - accumulator[3] += D; - accumulator[4] += E; - accumulator[5] += F; - accumulator[6] += G; - accumulator[7] += H; + //(update chaining values) (H1 , H2 , H3 , H4 ) <- (H1 + A, H2 + B, H3 + C, H4 + //+ D...) + accumulator[0] += A; + accumulator[1] += B; + accumulator[2] += C; + accumulator[3] += D; + accumulator[4] += E; + accumulator[5] += F; + accumulator[6] += G; + accumulator[7] += H; } -cx_err_t cx_sha256_update(cx_sha256_t *ctx, const uint8_t *data, size_t len) { - size_t r; - size_t blen; - - if (ctx == NULL) { - return CX_INVALID_PARAMETER; - } - if (data == NULL && len != 0) { - return CX_INVALID_PARAMETER; - } - - // --- init locals --- - blen = ctx->blen; - ctx->blen = 0; - - if (blen >= 64) { - return CX_INVALID_PARAMETER; - } - - // --- append input data and process all blocks --- - if (blen + len >= 64) { - r = 64 - blen; - do { - // if (ctx->header.counter == CX_HASH_MAX_BLOCK_COUNT) { - // return CX_INVALID_PARAMETER; - // } - memcpy(ctx->block + blen, data, r); - cx_sha256_block(ctx); - - blen = 0; - ctx->header.counter++; - data += r; - len -= r; - r = 64; - } while (len >= 64); - } - - // --- remind rest data--- - memcpy(ctx->block + blen, data, len); - blen += len; - ctx->blen = blen; - return CX_OK; +cx_err_t cx_sha256_update(cx_sha256_t *ctx, const uint8_t *data, size_t len) +{ + size_t r; + size_t blen; + + if (ctx == NULL) { + return CX_INVALID_PARAMETER; + } + if (data == NULL && len != 0) { + return CX_INVALID_PARAMETER; + } + + // --- init locals --- + blen = ctx->blen; + ctx->blen = 0; + + if (blen >= 64) { + return CX_INVALID_PARAMETER; + } + + // --- append input data and process all blocks --- + if (blen + len >= 64) { + r = 64 - blen; + do { + // if (ctx->header.counter == CX_HASH_MAX_BLOCK_COUNT) { + // return CX_INVALID_PARAMETER; + // } + memcpy(ctx->block + blen, data, r); + cx_sha256_block(ctx); + + blen = 0; + ctx->header.counter++; + data += r; + len -= r; + r = 64; + } while (len >= 64); + } + + // --- remind rest data--- + memcpy(ctx->block + blen, data, len); + blen += len; + ctx->blen = blen; + return CX_OK; } -cx_err_t cx_sha256_final(cx_sha256_t *ctx, uint8_t *digest) { - uint64_t bitlen; +cx_err_t cx_sha256_final(cx_sha256_t *ctx, uint8_t *digest) +{ + uint64_t bitlen; - // --- init locals --- - uint8_t *block = ctx->block; + // --- init locals --- + uint8_t *block = ctx->block; - block[ctx->blen] = 0x80; - ctx->blen++; + block[ctx->blen] = 0x80; + ctx->blen++; - bitlen = (((uint64_t)ctx->header.counter) * 64UL + (uint64_t)ctx->blen - 1UL) * 8UL; - // one more block? - if (64 - ctx->blen < 8) { + bitlen = (((uint64_t) ctx->header.counter) * 64UL + (uint64_t) ctx->blen - 1UL) * 8UL; + // one more block? + if (64 - ctx->blen < 8) { + memset(block + ctx->blen, 0, 64 - ctx->blen); + cx_sha256_block(ctx); + ctx->blen = 0; + } + // last block! memset(block + ctx->blen, 0, 64 - ctx->blen); - cx_sha256_block(ctx); - ctx->blen = 0; - } - // last block! - memset(block + ctx->blen, 0, 64 - ctx->blen); #ifdef ARCH_LITTLE_ENDIAN - *(uint64_t *)&block[64 - 8] = cx_swap_uint64(bitlen); + *(uint64_t *) &block[64 - 8] = cx_swap_uint64(bitlen); #else - (*(uint64_t *)&block[64 - 8]) = bitlen; + (*(uint64_t *) &block[64 - 8]) = bitlen; #endif - cx_sha256_block(ctx); - // provide result + cx_sha256_block(ctx); + // provide result #ifdef ARCH_LITTLE_ENDIAN - cx_swap_buffer32((uint32_t *)ctx->acc, 8); + cx_swap_buffer32((uint32_t *) ctx->acc, 8); #endif #if defined(HAVE_SHA224) - if (ctx->header.info->md_type == CX_SHA224) { - memcpy(digest, ctx->acc, CX_SHA224_SIZE); - } else + if (ctx->header.info->md_type == CX_SHA224) { + memcpy(digest, ctx->acc, CX_SHA224_SIZE); + } + else #endif - { - memcpy(digest, ctx->acc, CX_SHA256_SIZE); - } - return CX_OK; + { + memcpy(digest, ctx->acc, CX_SHA256_SIZE); + } + return CX_OK; } -size_t cx_hash_sha256(const uint8_t *in, size_t in_len, uint8_t *out, size_t out_len) { - if (out_len < CX_SHA256_SIZE) { - return 0; - } - cx_sha256_init_no_throw(&G_cx.sha256); - cx_sha256_update(&G_cx.sha256, in, in_len); - cx_sha256_final(&G_cx.sha256, out); - explicit_bzero(&G_cx.sha256, sizeof(cx_sha256_t)); - return CX_SHA256_SIZE; +size_t cx_hash_sha256(const uint8_t *in, size_t in_len, uint8_t *out, size_t out_len) +{ + if (out_len < CX_SHA256_SIZE) { + return 0; + } + cx_sha256_init_no_throw(&G_cx.sha256); + cx_sha256_update(&G_cx.sha256, in, in_len); + cx_sha256_final(&G_cx.sha256, out); + explicit_bzero(&G_cx.sha256, sizeof(cx_sha256_t)); + return CX_SHA256_SIZE; } -#endif // defined(HAVE_SHA255) || defined(HAVE_SHA224) +#endif // defined(HAVE_SHA255) || defined(HAVE_SHA224) diff --git a/lib_cxng/src/cx_sha256.h b/lib_cxng/src/cx_sha256.h index b1bdef406..a89a5cdff 100644 --- a/lib_cxng/src/cx_sha256.h +++ b/lib_cxng/src/cx_sha256.h @@ -10,14 +10,14 @@ #ifdef HAVE_SHA224 extern const cx_hash_info_t cx_sha224_info; -#endif // HAVE_SHA224 +#endif // HAVE_SHA224 #ifdef HAVE_SHA256 extern const cx_hash_info_t cx_sha256_info; -#endif // HAVE_SHA256 +#endif // HAVE_SHA256 cx_err_t cx_sha256_update(cx_sha256_t *ctx, const uint8_t *data, size_t len); cx_err_t cx_sha256_final(cx_sha256_t *ctx, uint8_t *digest); -#endif // CX_SHA256_H -#endif // HAVE_SHA256 +#endif // CX_SHA256_H +#endif // HAVE_SHA256 diff --git a/lib_cxng/src/cx_sha3.c b/lib_cxng/src/cx_sha3.c index c7d9e2179..c94d1e05c 100644 --- a/lib_cxng/src/cx_sha3.c +++ b/lib_cxng/src/cx_sha3.c @@ -1,20 +1,20 @@ /******************************************************************************* -* Ledger Nano S - Secure firmware -* (c) 2022 Ledger -* -* Licensed under the Apache License, Version 2.0 (the "License"); -* you may not use this file except in compliance with the License. -* You may obtain a copy of the License at -* -* http://www.apache.org/licenses/LICENSE-2.0 -* -* Unless required by applicable law or agreed to in writing, software -* distributed under the License is distributed on an "AS IS" BASIS, -* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -* See the License for the specific language governing permissions and -* limitations under the License. -********************************************************************************/ + * Ledger Nano S - Secure firmware + * (c) 2022 Ledger + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + ********************************************************************************/ #ifdef HAVE_SHA3 @@ -29,329 +29,352 @@ #error "Big endian architectures are not supported. Please abort your project" #endif -#ifndef NATIVE_64BITS // NO 64BITS natively supported by the compiler +#ifndef NATIVE_64BITS // NO 64BITS natively supported by the compiler #error sha3 require 64 bits support at compiler level (NATIVE_64BITS option) #endif -const cx_hash_info_t cx_sha3_info = { - CX_SHA3, - 0, - 0, - sizeof(cx_sha3_t), - NULL, - (cx_err_t (*)(cx_hash_t *ctx, const uint8_t *data, size_t len))cx_sha3_update, - (cx_err_t (*)(cx_hash_t *ctx, uint8_t *digest))cx_sha3_final, - (cx_err_t (*)(cx_hash_t *ctx, size_t output_size))cx_sha3_init_no_throw, - (size_t(*)(const cx_hash_t *ctx))cx_sha3_get_output_size -}; - -const cx_hash_info_t cx_keccak_info = { - CX_KECCAK, - 0, - 0, - sizeof(cx_sha3_t), - NULL, - (cx_err_t (*)(cx_hash_t *ctx, const uint8_t *data, size_t len))cx_sha3_update, - (cx_err_t (*)(cx_hash_t *ctx, uint8_t *digest))cx_sha3_final, - (cx_err_t (*)(cx_hash_t *ctx, size_t output_size))cx_keccak_init_no_throw, - (size_t(*)(const cx_hash_t *ctx))cx_sha3_get_output_size -}; - -const cx_hash_info_t cx_shake128_info = { - CX_SHAKE128, - 0, - 0, - sizeof(cx_sha3_t), - NULL, - (cx_err_t (*)(cx_hash_t *ctx, const uint8_t *data, size_t len))cx_sha3_update, - (cx_err_t (*)(cx_hash_t *ctx, uint8_t *digest))cx_sha3_final, - (cx_err_t (*)(cx_hash_t *ctx, size_t output_size))cx_shake128_init_no_throw, - (size_t(*)(const cx_hash_t *ctx))cx_sha3_get_output_size -}; - -const cx_hash_info_t cx_shake256_info = { - CX_SHAKE256, - 0, - 0, - sizeof(cx_sha3_t), - NULL, - (cx_err_t (*)(cx_hash_t *ctx, const uint8_t *data, size_t len))cx_sha3_update, - (cx_err_t (*)(cx_hash_t *ctx, uint8_t *digest))cx_sha3_final, - (cx_err_t (*)(cx_hash_t *ctx, size_t output_size))cx_shake256_init_no_throw, - (size_t(*)(const cx_hash_t *ctx))cx_sha3_get_output_size -}; +const cx_hash_info_t cx_sha3_info + = {CX_SHA3, + 0, + 0, + sizeof(cx_sha3_t), + NULL, + (cx_err_t(*)(cx_hash_t * ctx, const uint8_t *data, size_t len)) cx_sha3_update, + (cx_err_t(*)(cx_hash_t * ctx, uint8_t *digest)) cx_sha3_final, + (cx_err_t(*)(cx_hash_t * ctx, size_t output_size)) cx_sha3_init_no_throw, + (size_t(*)(const cx_hash_t *ctx)) cx_sha3_get_output_size}; + +const cx_hash_info_t cx_keccak_info + = {CX_KECCAK, + 0, + 0, + sizeof(cx_sha3_t), + NULL, + (cx_err_t(*)(cx_hash_t * ctx, const uint8_t *data, size_t len)) cx_sha3_update, + (cx_err_t(*)(cx_hash_t * ctx, uint8_t *digest)) cx_sha3_final, + (cx_err_t(*)(cx_hash_t * ctx, size_t output_size)) cx_keccak_init_no_throw, + (size_t(*)(const cx_hash_t *ctx)) cx_sha3_get_output_size}; + +const cx_hash_info_t cx_shake128_info + = {CX_SHAKE128, + 0, + 0, + sizeof(cx_sha3_t), + NULL, + (cx_err_t(*)(cx_hash_t * ctx, const uint8_t *data, size_t len)) cx_sha3_update, + (cx_err_t(*)(cx_hash_t * ctx, uint8_t *digest)) cx_sha3_final, + (cx_err_t(*)(cx_hash_t * ctx, size_t output_size)) cx_shake128_init_no_throw, + (size_t(*)(const cx_hash_t *ctx)) cx_sha3_get_output_size}; + +const cx_hash_info_t cx_shake256_info + = {CX_SHAKE256, + 0, + 0, + sizeof(cx_sha3_t), + NULL, + (cx_err_t(*)(cx_hash_t * ctx, const uint8_t *data, size_t len)) cx_sha3_update, + (cx_err_t(*)(cx_hash_t * ctx, uint8_t *digest)) cx_sha3_final, + (cx_err_t(*)(cx_hash_t * ctx, size_t output_size)) cx_shake256_init_no_throw, + (size_t(*)(const cx_hash_t *ctx)) cx_sha3_get_output_size}; // Assume state is a uint64_t array -#define S64(x, y) state[x + 5 * y] +#define S64(x, y) state[x + 5 * y] #define ROTL64(x, n) cx_rotl64(x, n) -static void cx_sha3_theta(uint64bits_t state[]) { - uint64bits_t C[5]; - uint64bits_t D[5]; - int i, j; +static void cx_sha3_theta(uint64bits_t state[]) +{ + uint64bits_t C[5]; + uint64bits_t D[5]; + int i, j; - for (i = 0; i < 5; i++) { - C[i] = S64(i, 0) ^ S64(i, 1) ^ S64(i, 2) ^ S64(i, 3) ^ S64(i, 4); - } - for (i = 0; i < 5; i++) { - D[i] = C[(i + 4) % 5] ^ ROTL64(C[(i + 1) % 5], 1); - for (j = 0; j < 5; j++) { - S64(i, j) ^= D[i]; + for (i = 0; i < 5; i++) { + C[i] = S64(i, 0) ^ S64(i, 1) ^ S64(i, 2) ^ S64(i, 3) ^ S64(i, 4); + } + for (i = 0; i < 5; i++) { + D[i] = C[(i + 4) % 5] ^ ROTL64(C[(i + 1) % 5], 1); + for (j = 0; j < 5; j++) { + S64(i, j) ^= D[i]; + } } - } } -static const uint8_t C_cx_pi_table[] = {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 const uint8_t C_cx_pi_table[] + = {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 const uint8_t C_cx_rho_table[] = {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 uint8_t C_cx_rho_table[] + = {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 void cx_sha3_rho_pi(uint64bits_t state[]) { - int i, j; - uint64bits_t A; - uint64bits_t tmp; +static void cx_sha3_rho_pi(uint64bits_t state[]) +{ + int i, j; + uint64bits_t A; + uint64bits_t tmp; - A = state[1]; - for (i = 0; i < 24; i++) { - j = C_cx_pi_table[i]; - tmp = state[j]; - state[j] = ROTL64(A, C_cx_rho_table[i]); - A = tmp; - } + A = state[1]; + for (i = 0; i < 24; i++) { + j = C_cx_pi_table[i]; + tmp = state[j]; + state[j] = ROTL64(A, C_cx_rho_table[i]); + A = tmp; + } } -static void cx_sha3_chi(uint64bits_t state[]) { - uint64bits_t C[5]; +static void cx_sha3_chi(uint64bits_t state[]) +{ + uint64bits_t C[5]; - int i, j; - for (j = 0; j < 5; j++) { - for (i = 0; i < 5; i++) { - C[i] = S64(i, j); - } - for (i = 0; i < 5; i++) { - S64(i, j) ^= (~C[(i + 1) % 5]) & C[(i + 2) % 5]; + int i, j; + for (j = 0; j < 5; j++) { + for (i = 0; i < 5; i++) { + C[i] = S64(i, j); + } + for (i = 0; i < 5; i++) { + S64(i, j) ^= (~C[(i + 1) % 5]) & C[(i + 2) % 5]; + } } - } } -static const uint64bits_t C_cx_iota_RC[24] = { - _64BITS(0x00000000, 0x00000001), _64BITS(0x00000000, 0x00008082), _64BITS(0x80000000, 0x0000808A), - _64BITS(0x80000000, 0x80008000), _64BITS(0x00000000, 0x0000808B), _64BITS(0x00000000, 0x80000001), - _64BITS(0x80000000, 0x80008081), _64BITS(0x80000000, 0x00008009), _64BITS(0x00000000, 0x0000008A), - _64BITS(0x00000000, 0x00000088), _64BITS(0x00000000, 0x80008009), _64BITS(0x00000000, 0x8000000A), - _64BITS(0x00000000, 0x8000808B), _64BITS(0x80000000, 0x0000008B), _64BITS(0x80000000, 0x00008089), - _64BITS(0x80000000, 0x00008003), _64BITS(0x80000000, 0x00008002), _64BITS(0x80000000, 0x00000080), - _64BITS(0x00000000, 0x0000800A), _64BITS(0x80000000, 0x8000000A), _64BITS(0x80000000, 0x80008081), - _64BITS(0x80000000, 0x00008080), _64BITS(0x00000000, 0x80000001), _64BITS(0x80000000, 0x80008008)}; - -static void cx_sha3_iota(uint64bits_t state[], int round) { - S64(0, 0) ^= C_cx_iota_RC[round]; +static const uint64bits_t C_cx_iota_RC[24] + = {_64BITS(0x00000000, 0x00000001), _64BITS(0x00000000, 0x00008082), + _64BITS(0x80000000, 0x0000808A), _64BITS(0x80000000, 0x80008000), + _64BITS(0x00000000, 0x0000808B), _64BITS(0x00000000, 0x80000001), + _64BITS(0x80000000, 0x80008081), _64BITS(0x80000000, 0x00008009), + _64BITS(0x00000000, 0x0000008A), _64BITS(0x00000000, 0x00000088), + _64BITS(0x00000000, 0x80008009), _64BITS(0x00000000, 0x8000000A), + _64BITS(0x00000000, 0x8000808B), _64BITS(0x80000000, 0x0000008B), + _64BITS(0x80000000, 0x00008089), _64BITS(0x80000000, 0x00008003), + _64BITS(0x80000000, 0x00008002), _64BITS(0x80000000, 0x00000080), + _64BITS(0x00000000, 0x0000800A), _64BITS(0x80000000, 0x8000000A), + _64BITS(0x80000000, 0x80008081), _64BITS(0x80000000, 0x00008080), + _64BITS(0x00000000, 0x80000001), _64BITS(0x80000000, 0x80008008)}; + +static void cx_sha3_iota(uint64bits_t state[], int round) +{ + S64(0, 0) ^= C_cx_iota_RC[round]; } -static bool check_hash_out_size(size_t size) { - switch (size) { - case 128: - case 224: - case 256: - case 384: - case 512: - return true; - default: - return false; - } +static bool check_hash_out_size(size_t size) +{ + switch (size) { + case 128: + case 224: + case 256: + case 384: + case 512: + return true; + default: + return false; + } } -cx_err_t cx_sha3_init_no_throw(cx_sha3_t *hash PLENGTH(sizeof(cx_sha3_t)), size_t size) { - if (!check_hash_out_size(size)) { - return CX_INVALID_PARAMETER; - } - memset(hash, 0, sizeof(cx_sha3_t)); - hash->header.info = &cx_sha3_info; - hash->output_size = size >> 3; - hash->block_size = (1600 - 2 * size) >> 3; - return CX_OK; +cx_err_t cx_sha3_init_no_throw(cx_sha3_t *hash PLENGTH(sizeof(cx_sha3_t)), size_t size) +{ + if (!check_hash_out_size(size)) { + return CX_INVALID_PARAMETER; + } + memset(hash, 0, sizeof(cx_sha3_t)); + hash->header.info = &cx_sha3_info; + hash->output_size = size >> 3; + hash->block_size = (1600 - 2 * size) >> 3; + return CX_OK; } -cx_err_t cx_keccak_init_no_throw(cx_sha3_t *hash PLENGTH(sizeof(cx_sha3_t)), size_t size) { - if (!check_hash_out_size(size)) { - return CX_INVALID_PARAMETER; - } - cx_sha3_init_no_throw(hash, size); - hash->header.info = &cx_keccak_info; - return CX_OK; +cx_err_t cx_keccak_init_no_throw(cx_sha3_t *hash PLENGTH(sizeof(cx_sha3_t)), size_t size) +{ + if (!check_hash_out_size(size)) { + return CX_INVALID_PARAMETER; + } + cx_sha3_init_no_throw(hash, size); + hash->header.info = &cx_keccak_info; + return CX_OK; } -cx_err_t cx_shake128_init_no_throw(cx_sha3_t *hash, size_t size) { - memset(hash, 0, sizeof(cx_sha3_t)); - if (size % 8 != 0) { - return CX_INVALID_PARAMETER; - } - hash->header.info = &cx_shake128_info; - hash->output_size = size / 8; - hash->block_size = (1600 - 2 * 128) >> 3; - return CX_OK; +cx_err_t cx_shake128_init_no_throw(cx_sha3_t *hash, size_t size) +{ + memset(hash, 0, sizeof(cx_sha3_t)); + if (size % 8 != 0) { + return CX_INVALID_PARAMETER; + } + hash->header.info = &cx_shake128_info; + hash->output_size = size / 8; + hash->block_size = (1600 - 2 * 128) >> 3; + return CX_OK; } -cx_err_t cx_shake256_init_no_throw(cx_sha3_t *hash, size_t size) { - memset(hash, 0, sizeof(cx_sha3_t)); - if (size % 8 != 0) { - return CX_INVALID_PARAMETER; - } - hash->header.info = &cx_shake256_info; - hash->output_size = size / 8; - hash->block_size = (1600 - 2 * 256) >> 3; - return CX_OK; +cx_err_t cx_shake256_init_no_throw(cx_sha3_t *hash, size_t size) +{ + memset(hash, 0, sizeof(cx_sha3_t)); + if (size % 8 != 0) { + return CX_INVALID_PARAMETER; + } + hash->header.info = &cx_shake256_info; + hash->output_size = size / 8; + hash->block_size = (1600 - 2 * 256) >> 3; + return CX_OK; } -cx_err_t cx_sha3_xof_init_no_throw(cx_sha3_t *hash PLENGTH(sizeof(cx_sha3_t)), size_t size, size_t out_length) { - if ((size != 128) && (size != 256)) { - return CX_INVALID_PARAMETER; - } - memset(hash, 0, sizeof(cx_sha3_t)); - if (size == 128) { - hash->header.info = &cx_shake128_info; - } else { - hash->header.info = &cx_shake256_info; - } - hash->output_size = out_length; - hash->block_size = (1600 - 2 * size) >> 3; - return CX_OK; +cx_err_t cx_sha3_xof_init_no_throw(cx_sha3_t *hash PLENGTH(sizeof(cx_sha3_t)), + size_t size, + size_t out_length) +{ + if ((size != 128) && (size != 256)) { + return CX_INVALID_PARAMETER; + } + memset(hash, 0, sizeof(cx_sha3_t)); + if (size == 128) { + hash->header.info = &cx_shake128_info; + } + else { + hash->header.info = &cx_shake256_info; + } + hash->output_size = out_length; + hash->block_size = (1600 - 2 * size) >> 3; + return CX_OK; } -void cx_sha3_block(cx_sha3_t *hash) { - uint64bits_t *block; - uint64bits_t *acc; - int r, i, n; - - block = (uint64bits_t *)hash->block; - acc = (uint64bits_t *)hash->acc; - - if (hash->block_size > 144) { - n = 21; - } else if (hash->block_size > 136) { - n = 18; - } else if (hash->block_size > 104) { - n = 17; - } else if (hash->block_size > 72) { - n = 13; - } else { - n = 9; - } - for (i = 0; i < n; i++) { - acc[i] ^= block[i]; - } - - for (r = 0; r < 24; r++) { - cx_sha3_theta(acc); - cx_sha3_rho_pi(acc); - cx_sha3_chi(acc); - cx_sha3_iota(acc, r); - } +void cx_sha3_block(cx_sha3_t *hash) +{ + uint64bits_t *block; + uint64bits_t *acc; + int r, i, n; + + block = (uint64bits_t *) hash->block; + acc = (uint64bits_t *) hash->acc; + + if (hash->block_size > 144) { + n = 21; + } + else if (hash->block_size > 136) { + n = 18; + } + else if (hash->block_size > 104) { + n = 17; + } + else if (hash->block_size > 72) { + n = 13; + } + else { + n = 9; + } + for (i = 0; i < n; i++) { + acc[i] ^= block[i]; + } + + for (r = 0; r < 24; r++) { + cx_sha3_theta(acc); + cx_sha3_rho_pi(acc); + cx_sha3_chi(acc); + cx_sha3_iota(acc, r); + } } -cx_err_t cx_sha3_update(cx_sha3_t *ctx, const uint8_t *data, size_t len) { - size_t r; - size_t block_size; - uint8_t *block; - size_t blen; - - if (ctx == NULL) { - return CX_INVALID_PARAMETER; - } - if (data == NULL) { - return len == 0 ? CX_OK : CX_INVALID_PARAMETER; - } - - block_size = ctx->block_size; - if (block_size > 200) { - return CX_INVALID_PARAMETER; - } - - block = ctx->block; - blen = ctx->blen; - ctx->blen = 0; - - if (blen >= block_size) { - return CX_INVALID_PARAMETER; - } - - // --- append input data and process all blocks --- - if ((blen + len) >= block_size) { - r = block_size - blen; - do { - if (ctx->header.counter == CX_HASH_MAX_BLOCK_COUNT) { - return INVALID_PARAMETER; - } - memcpy(block + blen, data, r); - cx_sha3_block(ctx); - - blen = 0; - ctx->header.counter++; - data += r; - len -= r; - r = block_size; - } while (len >= block_size); - } - - // --- remind rest data--- - memcpy(block + blen, data, len); - blen += len; - ctx->blen = blen; - return CX_OK; +cx_err_t cx_sha3_update(cx_sha3_t *ctx, const uint8_t *data, size_t len) +{ + size_t r; + size_t block_size; + uint8_t *block; + size_t blen; + + if (ctx == NULL) { + return CX_INVALID_PARAMETER; + } + if (data == NULL) { + return len == 0 ? CX_OK : CX_INVALID_PARAMETER; + } + + block_size = ctx->block_size; + if (block_size > 200) { + return CX_INVALID_PARAMETER; + } + + block = ctx->block; + blen = ctx->blen; + ctx->blen = 0; + + if (blen >= block_size) { + return CX_INVALID_PARAMETER; + } + + // --- append input data and process all blocks --- + if ((blen + len) >= block_size) { + r = block_size - blen; + do { + if (ctx->header.counter == CX_HASH_MAX_BLOCK_COUNT) { + return INVALID_PARAMETER; + } + memcpy(block + blen, data, r); + cx_sha3_block(ctx); + + blen = 0; + ctx->header.counter++; + data += r; + len -= r; + r = block_size; + } while (len >= block_size); + } + + // --- remind rest data--- + memcpy(block + blen, data, len); + blen += len; + ctx->blen = blen; + return CX_OK; } -cx_err_t cx_sha3_final(cx_sha3_t *hash, uint8_t *digest) { - size_t block_size; - uint8_t *block; - size_t blen; - size_t len; - - block = hash->block; - block_size = hash->block_size; - blen = hash->blen; - - // one more block? - if (hash->header.info->md_type == CX_KECCAK || hash->header.info->md_type == CX_SHA3) { - // last block! - memset(block + blen, 0, (200 - blen)); - - if (hash->header.info->md_type == CX_KECCAK) { - block[blen] |= 01; - } else { - block[blen] |= 06; +cx_err_t cx_sha3_final(cx_sha3_t *hash, uint8_t *digest) +{ + size_t block_size; + uint8_t *block; + size_t blen; + size_t len; + + block = hash->block; + block_size = hash->block_size; + blen = hash->blen; + + // one more block? + if (hash->header.info->md_type == CX_KECCAK || hash->header.info->md_type == CX_SHA3) { + // last block! + memset(block + blen, 0, (200 - blen)); + + if (hash->header.info->md_type == CX_KECCAK) { + block[blen] |= 01; + } + else { + block[blen] |= 06; + } + block[block_size - 1] |= 0x80; + cx_sha3_block(hash); + + // provide result + len = (hash)->output_size; + memcpy(digest, hash->acc, len); } - block[block_size - 1] |= 0x80; - cx_sha3_block(hash); - - // provide result - len = (hash)->output_size; - memcpy(digest, hash->acc, len); - } else { - // CX_SHA3_XOF - memset(block + blen, 0, (200 - blen)); - block[blen] |= 0x1F; - block[block_size - 1] |= 0x80; - cx_sha3_block(hash); - // provide result - len = hash->output_size; - blen = len; - - memset(block, 0, 200); - - while (blen > block_size) { - memcpy(digest, hash->acc, block_size); - blen -= block_size; - digest += block_size; - cx_sha3_block(hash); + else { + // CX_SHA3_XOF + memset(block + blen, 0, (200 - blen)); + block[blen] |= 0x1F; + block[block_size - 1] |= 0x80; + cx_sha3_block(hash); + // provide result + len = hash->output_size; + blen = len; + + memset(block, 0, 200); + + while (blen > block_size) { + memcpy(digest, hash->acc, block_size); + blen -= block_size; + digest += block_size; + cx_sha3_block(hash); + } + memcpy(digest, hash->acc, blen); } - memcpy(digest, hash->acc, blen); - } - return CX_OK; + return CX_OK; } -size_t cx_sha3_get_output_size(const cx_sha3_t *ctx) { - return ctx->output_size; +size_t cx_sha3_get_output_size(const cx_sha3_t *ctx) +{ + return ctx->output_size; } -#endif // HAVE_SHA3 +#endif // HAVE_SHA3 diff --git a/lib_cxng/src/cx_sha3.h b/lib_cxng/src/cx_sha3.h index 7594fd160..96bab3f4c 100644 --- a/lib_cxng/src/cx_sha3.h +++ b/lib_cxng/src/cx_sha3.h @@ -12,8 +12,8 @@ extern const cx_hash_info_t cx_shake256_info; cx_err_t cx_sha3_update(cx_sha3_t *ctx, const uint8_t *data, size_t len); cx_err_t cx_sha3_final(cx_sha3_t *ctx, uint8_t *digest); -size_t cx_sha3_get_output_size(const cx_sha3_t *ctx); +size_t cx_sha3_get_output_size(const cx_sha3_t *ctx); -#endif // CX_SHA3_H +#endif // CX_SHA3_H -#endif // HAVE_SHA3 +#endif // HAVE_SHA3 diff --git a/lib_cxng/src/cx_sha512.c b/lib_cxng/src/cx_sha512.c index 69bcf353c..4065ce8be 100644 --- a/lib_cxng/src/cx_sha512.c +++ b/lib_cxng/src/cx_sha512.c @@ -1,20 +1,20 @@ /******************************************************************************* -* Ledger Nano S - Secure firmware -* (c) 2022 Ledger -* -* Licensed under the Apache License, Version 2.0 (the "License"); -* you may not use this file except in compliance with the License. -* You may obtain a copy of the License at -* -* http://www.apache.org/licenses/LICENSE-2.0 -* -* Unless required by applicable law or agreed to in writing, software -* distributed under the License is distributed on an "AS IS" BASIS, -* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -* See the License for the specific language governing permissions and -* limitations under the License. -********************************************************************************/ + * Ledger Nano S - Secure firmware + * (c) 2022 Ledger + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT 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(HAVE_SHA512) || defined(HAVE_SHA384) @@ -25,119 +25,128 @@ #include #ifdef HAVE_SHA384 -const cx_hash_info_t cx_sha384_info = { - CX_SHA384, - CX_SHA384_SIZE, - SHA512_BLOCK_SIZE, - sizeof(cx_sha512_t), - (cx_err_t (*)(cx_hash_t *ctx))cx_sha384_init_no_throw, - (cx_err_t (*)(cx_hash_t *ctx, const uint8_t *data, size_t len))cx_sha512_update, - (cx_err_t (*)(cx_hash_t *ctx, uint8_t *digest))cx_sha512_final, - NULL, - NULL -}; -#endif // HAVE_SHA384 +const cx_hash_info_t cx_sha384_info + = {CX_SHA384, + CX_SHA384_SIZE, + SHA512_BLOCK_SIZE, + sizeof(cx_sha512_t), + (cx_err_t(*)(cx_hash_t * ctx)) cx_sha384_init_no_throw, + (cx_err_t(*)(cx_hash_t * ctx, const uint8_t *data, size_t len)) cx_sha512_update, + (cx_err_t(*)(cx_hash_t * ctx, uint8_t *digest)) cx_sha512_final, + NULL, + NULL}; +#endif // HAVE_SHA384 #ifdef HAVE_SHA512 -const cx_hash_info_t cx_sha512_info = { - CX_SHA512, - CX_SHA512_SIZE, - SHA512_BLOCK_SIZE, - sizeof(cx_sha512_t), - (cx_err_t (*)(cx_hash_t *ctx))cx_sha512_init_no_throw, - (cx_err_t (*)(cx_hash_t *ctx, const uint8_t *data, size_t len))cx_sha512_update, - (cx_err_t (*)(cx_hash_t *ctx, uint8_t *digest))cx_sha512_final, - NULL, - NULL -}; -#endif // HAVE_SHA512 +const cx_hash_info_t cx_sha512_info + = {CX_SHA512, + CX_SHA512_SIZE, + SHA512_BLOCK_SIZE, + sizeof(cx_sha512_t), + (cx_err_t(*)(cx_hash_t * ctx)) cx_sha512_init_no_throw, + (cx_err_t(*)(cx_hash_t * ctx, const uint8_t *data, size_t len)) cx_sha512_update, + (cx_err_t(*)(cx_hash_t * ctx, uint8_t *digest)) cx_sha512_final, + NULL, + NULL}; +#endif // HAVE_SHA512 #ifndef HAVE_SHA512_WITH_INIT_ALT_METHOD #if defined(HAVE_SHA384) -static const uint64bits_t hzero_384[] = {_64BITS(0xcbbb9d5d, 0xc1059ed8), _64BITS(0x629a292a, 0x367cd507), - _64BITS(0x9159015a, 0x3070dd17), _64BITS(0x152fecd8, 0xf70e5939), - _64BITS(0x67332667, 0xffc00b31), _64BITS(0x8eb44a87, 0x68581511), - _64BITS(0xdb0c2e0d, 0x64f98fa7), _64BITS(0x47b5481d, 0xbefa4fa4)}; +static const uint64bits_t hzero_384[] = {_64BITS(0xcbbb9d5d, 0xc1059ed8), + _64BITS(0x629a292a, 0x367cd507), + _64BITS(0x9159015a, 0x3070dd17), + _64BITS(0x152fecd8, 0xf70e5939), + _64BITS(0x67332667, 0xffc00b31), + _64BITS(0x8eb44a87, 0x68581511), + _64BITS(0xdb0c2e0d, 0x64f98fa7), + _64BITS(0x47b5481d, 0xbefa4fa4)}; #endif #if defined(HAVE_SHA512) -static const uint64bits_t hzero[] = {_64BITS(0x6a09e667, 0xf3bcc908), _64BITS(0xbb67ae85, 0x84caa73b), - _64BITS(0x3c6ef372, 0xfe94f82b), _64BITS(0xa54ff53a, 0x5f1d36f1), - _64BITS(0x510e527f, 0xade682d1), _64BITS(0x9b05688c, 0x2b3e6c1f), - _64BITS(0x1f83d9ab, 0xfb41bd6b), _64BITS(0x5be0cd19, 0x137e2179)}; +static const uint64bits_t hzero[] = {_64BITS(0x6a09e667, 0xf3bcc908), + _64BITS(0xbb67ae85, 0x84caa73b), + _64BITS(0x3c6ef372, 0xfe94f82b), + _64BITS(0xa54ff53a, 0x5f1d36f1), + _64BITS(0x510e527f, 0xade682d1), + _64BITS(0x9b05688c, 0x2b3e6c1f), + _64BITS(0x1f83d9ab, 0xfb41bd6b), + _64BITS(0x5be0cd19, 0x137e2179)}; #endif #if defined(HAVE_SHA384) -cx_err_t cx_sha384_init_no_throw(cx_sha512_t *hash) { - memset(hash, 0, sizeof(cx_sha512_t)); - hash->header.info = &cx_sha384_info; - memmove(hash->acc, hzero_384, sizeof(hzero_384)); - return CX_OK; +cx_err_t cx_sha384_init_no_throw(cx_sha512_t *hash) +{ + memset(hash, 0, sizeof(cx_sha512_t)); + hash->header.info = &cx_sha384_info; + memmove(hash->acc, hzero_384, sizeof(hzero_384)); + return CX_OK; } #endif #if defined(HAVE_SHA512) -cx_err_t cx_sha512_init_no_throw(cx_sha512_t *hash) { - memset(hash, 0, sizeof(cx_sha512_t)); - hash->header.info = &cx_sha512_info; - memmove(hash->acc, hzero, sizeof(hzero)); - return CX_OK; +cx_err_t cx_sha512_init_no_throw(cx_sha512_t *hash) +{ + memset(hash, 0, sizeof(cx_sha512_t)); + hash->header.info = &cx_sha512_info; + memmove(hash->acc, hzero, sizeof(hzero)); + return CX_OK; } #endif -#endif // HAVE_SHA512_WITH_INIT_ALT_METHOD - +#endif // HAVE_SHA512_WITH_INIT_ALT_METHOD #ifndef HAVE_SHA512_WITH_BLOCK_ALT_METHOD -#ifndef NATIVE_64BITS // NO 64BITS natively supported by the compiler +#ifndef NATIVE_64BITS // NO 64BITS natively supported by the compiler #define rotR64(x, n) cx_rotr64(&x, n) -#define shR64(x, n) cx_shr64(&x, n) - -static void sig512(uint64bits_t *x, uint8_t a, uint8_t b, uint8_t c) { - uint64bits_t x1, x2, x3; - - ASSIGN64(x1, *x); - ASSIGN64(x2, *x); - ASSIGN64(x3, *x); - rotR64(x1, a); - rotR64(x2, b); - shR64(x3, c); - x->l = x1.l ^ x2.l ^ x3.l; - x->h = x1.h ^ x2.h ^ x3.h; +#define shR64(x, n) cx_shr64(&x, n) + +static void sig512(uint64bits_t *x, uint8_t a, uint8_t b, uint8_t c) +{ + uint64bits_t x1, x2, x3; + + ASSIGN64(x1, *x); + ASSIGN64(x2, *x); + ASSIGN64(x3, *x); + rotR64(x1, a); + rotR64(x2, b); + shR64(x3, c); + x->l = x1.l ^ x2.l ^ x3.l; + x->h = x1.h ^ x2.h ^ x3.h; } -static void sum512(uint64bits_t *x, uint8_t a, uint8_t b, uint8_t c) { - uint64bits_t x1, x2, x3; - - ASSIGN64(x1, *x); - ASSIGN64(x2, *x); - ASSIGN64(x3, *x); - rotR64((x1), a); - rotR64((x2), b); - rotR64((x3), c); - x->l = x1.l ^ x2.l ^ x3.l; - x->h = x1.h ^ x2.h ^ x3.h; +static void sum512(uint64bits_t *x, uint8_t a, uint8_t b, uint8_t c) +{ + uint64bits_t x1, x2, x3; + + ASSIGN64(x1, *x); + ASSIGN64(x2, *x); + ASSIGN64(x3, *x); + rotR64((x1), a); + rotR64((x2), b); + rotR64((x3), c); + x->l = x1.l ^ x2.l ^ x3.l; + x->h = x1.h ^ x2.h ^ x3.h; } #define sigma0(x) sig512(&x, 1, 8, 7) #define sigma1(x) sig512(&x, 19, 61, 6) -#define sum0(x) sum512(&x, 28, 34, 39) -#define sum1(x) sum512(&x, 14, 18, 41) +#define sum0(x) sum512(&x, 28, 34, 39) +#define sum1(x) sum512(&x, 14, 18, 41) // ( ((x) & (y)) ^ (~(x) & (z)) ) -#define ch(r, x, y, z) \ - r.l = ((x.l) & (y.l)) ^ (~(x.l) & (z.l)); \ - r.h = ((x.h) & (y.h)) ^ (~(x.h) & (z.h)) +#define ch(r, x, y, z) \ + r.l = ((x.l) & (y.l)) ^ (~(x.l) & (z.l)); \ + r.h = ((x.h) & (y.h)) ^ (~(x.h) & (z.h)) //( ((x) & (y)) ^ ( (x) & (z)) ^ ((y) & (z)) ) -#define maj(r, x, y, z) \ - r.l = ((x.l) & (y.l)) ^ ((x.l) & (z.l)) ^ ((y.l) & (z.l)); \ - r.h = ((x.h) & (y.h)) ^ ((x.h) & (z.h)) ^ ((y.h) & (z.h)) +#define maj(r, x, y, z) \ + r.l = ((x.l) & (y.l)) ^ ((x.l) & (z.l)) ^ ((y.l) & (z.l)); \ + r.h = ((x.h) & (y.h)) ^ ((x.h) & (z.h)) ^ ((y.h) & (z.h)) -#else // NATIVE_64BITS +#else // NATIVE_64BITS #define rotR64(x, n) cx_rotr64(x, n) -#define shR64(x, n) cx_shr64(x, n) +#define shR64(x, n) cx_shr64(x, n) #define sig512(x, a, b, c) (rotR64((x), a) ^ rotR64((x), b) ^ shR64((x), c)) @@ -145,53 +154,67 @@ static void sum512(uint64bits_t *x, uint8_t a, uint8_t b, uint8_t c) { #define sigma0(x) sig512(x, 1, 8, 7) #define sigma1(x) sig512(x, 19, 61, 6) -#define sum0(x) sum512(x, 28, 34, 39) -#define sum1(x) sum512(x, 14, 18, 41) +#define sum0(x) sum512(x, 28, 34, 39) +#define sum1(x) sum512(x, 14, 18, 41) -#define ch(x, y, z) (((x) & (y)) ^ (~(x) & (z))) +#define ch(x, y, z) (((x) & (y)) ^ (~(x) & (z))) #define maj(x, y, z) (((x) & (y)) ^ ((x) & (z)) ^ ((y) & (z))) -#endif // NATIVE_64BITS? +#endif // NATIVE_64BITS? static const uint64bits_t primeSqrt[] = { - _64BITS(0x428a2f98, 0xd728ae22), _64BITS(0x71374491, 0x23ef65cd), _64BITS(0xb5c0fbcf, 0xec4d3b2f), - _64BITS(0xe9b5dba5, 0x8189dbbc), _64BITS(0x3956c25b, 0xf348b538), _64BITS(0x59f111f1, 0xb605d019), - _64BITS(0x923f82a4, 0xaf194f9b), _64BITS(0xab1c5ed5, 0xda6d8118), _64BITS(0xd807aa98, 0xa3030242), - _64BITS(0x12835b01, 0x45706fbe), _64BITS(0x243185be, 0x4ee4b28c), _64BITS(0x550c7dc3, 0xd5ffb4e2), - _64BITS(0x72be5d74, 0xf27b896f), _64BITS(0x80deb1fe, 0x3b1696b1), _64BITS(0x9bdc06a7, 0x25c71235), - _64BITS(0xc19bf174, 0xcf692694), _64BITS(0xe49b69c1, 0x9ef14ad2), _64BITS(0xefbe4786, 0x384f25e3), - _64BITS(0x0fc19dc6, 0x8b8cd5b5), _64BITS(0x240ca1cc, 0x77ac9c65), _64BITS(0x2de92c6f, 0x592b0275), - _64BITS(0x4a7484aa, 0x6ea6e483), _64BITS(0x5cb0a9dc, 0xbd41fbd4), _64BITS(0x76f988da, 0x831153b5), - _64BITS(0x983e5152, 0xee66dfab), _64BITS(0xa831c66d, 0x2db43210), _64BITS(0xb00327c8, 0x98fb213f), - _64BITS(0xbf597fc7, 0xbeef0ee4), _64BITS(0xc6e00bf3, 0x3da88fc2), _64BITS(0xd5a79147, 0x930aa725), - _64BITS(0x06ca6351, 0xe003826f), _64BITS(0x14292967, 0x0a0e6e70), _64BITS(0x27b70a85, 0x46d22ffc), - _64BITS(0x2e1b2138, 0x5c26c926), _64BITS(0x4d2c6dfc, 0x5ac42aed), _64BITS(0x53380d13, 0x9d95b3df), - _64BITS(0x650a7354, 0x8baf63de), _64BITS(0x766a0abb, 0x3c77b2a8), _64BITS(0x81c2c92e, 0x47edaee6), - _64BITS(0x92722c85, 0x1482353b), _64BITS(0xa2bfe8a1, 0x4cf10364), _64BITS(0xa81a664b, 0xbc423001), - _64BITS(0xc24b8b70, 0xd0f89791), _64BITS(0xc76c51a3, 0x0654be30), _64BITS(0xd192e819, 0xd6ef5218), - _64BITS(0xd6990624, 0x5565a910), _64BITS(0xf40e3585, 0x5771202a), _64BITS(0x106aa070, 0x32bbd1b8), - _64BITS(0x19a4c116, 0xb8d2d0c8), _64BITS(0x1e376c08, 0x5141ab53), _64BITS(0x2748774c, 0xdf8eeb99), - _64BITS(0x34b0bcb5, 0xe19b48a8), _64BITS(0x391c0cb3, 0xc5c95a63), _64BITS(0x4ed8aa4a, 0xe3418acb), - _64BITS(0x5b9cca4f, 0x7763e373), _64BITS(0x682e6ff3, 0xd6b2b8a3), _64BITS(0x748f82ee, 0x5defb2fc), - _64BITS(0x78a5636f, 0x43172f60), _64BITS(0x84c87814, 0xa1f0ab72), _64BITS(0x8cc70208, 0x1a6439ec), - _64BITS(0x90befffa, 0x23631e28), _64BITS(0xa4506ceb, 0xde82bde9), _64BITS(0xbef9a3f7, 0xb2c67915), - _64BITS(0xc67178f2, 0xe372532b), _64BITS(0xca273ece, 0xea26619c), _64BITS(0xd186b8c7, 0x21c0c207), - _64BITS(0xeada7dd6, 0xcde0eb1e), _64BITS(0xf57d4f7f, 0xee6ed178), _64BITS(0x06f067aa, 0x72176fba), - _64BITS(0x0a637dc5, 0xa2c898a6), _64BITS(0x113f9804, 0xbef90dae), _64BITS(0x1b710b35, 0x131c471b), - _64BITS(0x28db77f5, 0x23047d84), _64BITS(0x32caab7b, 0x40c72493), _64BITS(0x3c9ebe0a, 0x15c9bebc), - _64BITS(0x431d67c4, 0x9c100d4c), _64BITS(0x4cc5d4be, 0xcb3e42b6), _64BITS(0x597f299c, 0xfc657e2a), + _64BITS(0x428a2f98, 0xd728ae22), _64BITS(0x71374491, 0x23ef65cd), + _64BITS(0xb5c0fbcf, 0xec4d3b2f), _64BITS(0xe9b5dba5, 0x8189dbbc), + _64BITS(0x3956c25b, 0xf348b538), _64BITS(0x59f111f1, 0xb605d019), + _64BITS(0x923f82a4, 0xaf194f9b), _64BITS(0xab1c5ed5, 0xda6d8118), + _64BITS(0xd807aa98, 0xa3030242), _64BITS(0x12835b01, 0x45706fbe), + _64BITS(0x243185be, 0x4ee4b28c), _64BITS(0x550c7dc3, 0xd5ffb4e2), + _64BITS(0x72be5d74, 0xf27b896f), _64BITS(0x80deb1fe, 0x3b1696b1), + _64BITS(0x9bdc06a7, 0x25c71235), _64BITS(0xc19bf174, 0xcf692694), + _64BITS(0xe49b69c1, 0x9ef14ad2), _64BITS(0xefbe4786, 0x384f25e3), + _64BITS(0x0fc19dc6, 0x8b8cd5b5), _64BITS(0x240ca1cc, 0x77ac9c65), + _64BITS(0x2de92c6f, 0x592b0275), _64BITS(0x4a7484aa, 0x6ea6e483), + _64BITS(0x5cb0a9dc, 0xbd41fbd4), _64BITS(0x76f988da, 0x831153b5), + _64BITS(0x983e5152, 0xee66dfab), _64BITS(0xa831c66d, 0x2db43210), + _64BITS(0xb00327c8, 0x98fb213f), _64BITS(0xbf597fc7, 0xbeef0ee4), + _64BITS(0xc6e00bf3, 0x3da88fc2), _64BITS(0xd5a79147, 0x930aa725), + _64BITS(0x06ca6351, 0xe003826f), _64BITS(0x14292967, 0x0a0e6e70), + _64BITS(0x27b70a85, 0x46d22ffc), _64BITS(0x2e1b2138, 0x5c26c926), + _64BITS(0x4d2c6dfc, 0x5ac42aed), _64BITS(0x53380d13, 0x9d95b3df), + _64BITS(0x650a7354, 0x8baf63de), _64BITS(0x766a0abb, 0x3c77b2a8), + _64BITS(0x81c2c92e, 0x47edaee6), _64BITS(0x92722c85, 0x1482353b), + _64BITS(0xa2bfe8a1, 0x4cf10364), _64BITS(0xa81a664b, 0xbc423001), + _64BITS(0xc24b8b70, 0xd0f89791), _64BITS(0xc76c51a3, 0x0654be30), + _64BITS(0xd192e819, 0xd6ef5218), _64BITS(0xd6990624, 0x5565a910), + _64BITS(0xf40e3585, 0x5771202a), _64BITS(0x106aa070, 0x32bbd1b8), + _64BITS(0x19a4c116, 0xb8d2d0c8), _64BITS(0x1e376c08, 0x5141ab53), + _64BITS(0x2748774c, 0xdf8eeb99), _64BITS(0x34b0bcb5, 0xe19b48a8), + _64BITS(0x391c0cb3, 0xc5c95a63), _64BITS(0x4ed8aa4a, 0xe3418acb), + _64BITS(0x5b9cca4f, 0x7763e373), _64BITS(0x682e6ff3, 0xd6b2b8a3), + _64BITS(0x748f82ee, 0x5defb2fc), _64BITS(0x78a5636f, 0x43172f60), + _64BITS(0x84c87814, 0xa1f0ab72), _64BITS(0x8cc70208, 0x1a6439ec), + _64BITS(0x90befffa, 0x23631e28), _64BITS(0xa4506ceb, 0xde82bde9), + _64BITS(0xbef9a3f7, 0xb2c67915), _64BITS(0xc67178f2, 0xe372532b), + _64BITS(0xca273ece, 0xea26619c), _64BITS(0xd186b8c7, 0x21c0c207), + _64BITS(0xeada7dd6, 0xcde0eb1e), _64BITS(0xf57d4f7f, 0xee6ed178), + _64BITS(0x06f067aa, 0x72176fba), _64BITS(0x0a637dc5, 0xa2c898a6), + _64BITS(0x113f9804, 0xbef90dae), _64BITS(0x1b710b35, 0x131c471b), + _64BITS(0x28db77f5, 0x23047d84), _64BITS(0x32caab7b, 0x40c72493), + _64BITS(0x3c9ebe0a, 0x15c9bebc), _64BITS(0x431d67c4, 0x9c100d4c), + _64BITS(0x4cc5d4be, 0xcb3e42b6), _64BITS(0x597f299c, 0xfc657e2a), _64BITS(0x5fcb6fab, 0x3ad6faec), _64BITS(0x6c44198c, 0x4a475817)}; -void cx_sha512_block(cx_sha512_t *hash) { - uint8_t j; - uint64bits_t t1, t2; +void cx_sha512_block(cx_sha512_t *hash) +{ + uint8_t j; + uint64bits_t t1, t2; - uint64bits_t *accumulator; - uint64bits_t *X; - struct { - uint64bits_t a, b, c, d, e, f, g, h; - } ACC; + uint64bits_t *accumulator; + uint64bits_t *X; + struct { + uint64bits_t a, b, c, d, e, f, g, h; + } ACC; #define A ACC.a #define B ACC.b #define C ACC.c @@ -201,253 +224,257 @@ void cx_sha512_block(cx_sha512_t *hash) { #define G ACC.g #define H ACC.h - X = (uint64bits_t *)(&hash->block[0]); - accumulator = (uint64bits_t *)(&hash->acc[0]); // only work because of indexing zero! - A = accumulator[0]; - B = accumulator[1]; - C = accumulator[2]; - D = accumulator[3]; - E = accumulator[4]; - F = accumulator[5]; - G = accumulator[6]; - H = accumulator[7]; + X = (uint64bits_t *) (&hash->block[0]); + accumulator = (uint64bits_t *) (&hash->acc[0]); // only work because of indexing zero! + A = accumulator[0]; + B = accumulator[1]; + C = accumulator[2]; + D = accumulator[3]; + E = accumulator[4]; + F = accumulator[5]; + G = accumulator[6]; + H = accumulator[7]; #ifdef ARCH_LITTLE_ENDIAN - cx_swap_buffer64(X, 16); + cx_swap_buffer64(X, 16); #endif - // init - /* - * T1 = Sum_1_512(e) + Chg(e,f,g) + K_t_512 + Wt - * T2 = Sum_0_512(a) + Maj(abc) - * h = g ; - * g = f; - * f = e; - * e = d + T1; - * d = c; - * c = b; - * b = a; - * a = T1 + T2; - */ - for (j = 0; j < 80; j++) { -#ifndef NATIVE_64BITS - uint64bits_t r; - - /* for j in 16 to 63, Xj <- (Sigma_1_512( Xj-2) + Xj-7 + Sigma_0_512(Xj-15) - * + Xj-16 ). */ - if (j >= 16) { - // sigma1(X[(j-2) & 0xF]) - ASSIGN64(t2, X[(j - 2) & 0xF]); - sigma1(t2); - //+ X[(j-7) & 0xF] - ADD64(t2, X[(j - 7) & 0xF]); - //+ sigma0(X[(j-15) & 0xF] - ASSIGN64(t1, X[(j - 15) & 0xF]); - sigma0(t1); - ADD64(t2, t1); - //+ X[(j-16) & 0xF]) - ADD64(t2, X[(j - 16) & 0xF]); - // assign - ASSIGN64(X[j & 0xF], t2); - } - - /// t1 = H + sum1(E) + ch(E,F,G) + primeSqrt[j] + X[j&0xF]; - // H - ASSIGN64(t1, H); - //+sum1(E) - ASSIGN64(r, E); - sum1(r); - ADD64(t1, r); - //+ch(E,F,G) - ch(r, E, F, G); - ADD64(t1, r); - //+primeSqrt[j] - ASSIGN64(r, primeSqrt[j]); - ADD64(t1, r); // ADD64(t1,primeSqrt[j]); - //+X[j&0xF] - ADD64(t1, X[j & 0xF]); - - /// t2 = sum0(A) + maj(A,B,C); - // sum0(A) - ASSIGN64(t2, A); - sum0(t2); - //+maj(A,B,C); - maj(r, A, B, C); - ADD64(t2, r); - + // init /* - H = G ; - G = F; - F = E; - E = D+t1; - D = C; - C = B; - B = A; - A = t1+t2; - */ - memmove(&ACC[1], &ACC[0], sizeof(ACC) - sizeof(uint64bits_t)); - // E += t1; - ADD64(E, t1); - // A = t1+t2; - ASSIGN64(A, t1); - ADD64(A, t2); -#else // no NATIVE_64BITS - /* for j in 16 to 63, Xj <- (Sigma_1_512( Xj-2) + Xj-7 + Sigma_0_512(Xj-15) - * + Xj-16 ). */ - if (j >= 16) { - uint64bits_t xj2, xj15; - xj2 = X[(j - 2) & 0xF]; - xj15 = X[(j - 15) & 0xF]; - X[j & 0xF] = (sigma1(xj2) + X[(j - 7) & 0xF] + sigma0(xj15) + X[(j - 16) & 0xF]); + * T1 = Sum_1_512(e) + Chg(e,f,g) + K_t_512 + Wt + * T2 = Sum_0_512(a) + Maj(abc) + * h = g ; + * g = f; + * f = e; + * e = d + T1; + * d = c; + * c = b; + * b = a; + * a = T1 + T2; + */ + for (j = 0; j < 80; j++) { +#ifndef NATIVE_64BITS + uint64bits_t r; + + /* for j in 16 to 63, Xj <- (Sigma_1_512( Xj-2) + Xj-7 + Sigma_0_512(Xj-15) + * + Xj-16 ). */ + if (j >= 16) { + // sigma1(X[(j-2) & 0xF]) + ASSIGN64(t2, X[(j - 2) & 0xF]); + sigma1(t2); + //+ X[(j-7) & 0xF] + ADD64(t2, X[(j - 7) & 0xF]); + //+ sigma0(X[(j-15) & 0xF] + ASSIGN64(t1, X[(j - 15) & 0xF]); + sigma0(t1); + ADD64(t2, t1); + //+ X[(j-16) & 0xF]) + ADD64(t2, X[(j - 16) & 0xF]); + // assign + ASSIGN64(X[j & 0xF], t2); + } + + /// t1 = H + sum1(E) + ch(E,F,G) + primeSqrt[j] + X[j&0xF]; + // H + ASSIGN64(t1, H); + //+sum1(E) + ASSIGN64(r, E); + sum1(r); + ADD64(t1, r); + //+ch(E,F,G) + ch(r, E, F, G); + ADD64(t1, r); + //+primeSqrt[j] + ASSIGN64(r, primeSqrt[j]); + ADD64(t1, r); // ADD64(t1,primeSqrt[j]); + //+X[j&0xF] + ADD64(t1, X[j & 0xF]); + + /// t2 = sum0(A) + maj(A,B,C); + // sum0(A) + ASSIGN64(t2, A); + sum0(t2); + //+maj(A,B,C); + maj(r, A, B, C); + ADD64(t2, r); + + /* + H = G ; + G = F; + F = E; + E = D+t1; + D = C; + C = B; + B = A; + A = t1+t2; + */ + memmove(&ACC[1], &ACC[0], sizeof(ACC) - sizeof(uint64bits_t)); + // E += t1; + ADD64(E, t1); + // A = t1+t2; + ASSIGN64(A, t1); + ADD64(A, t2); +#else // no NATIVE_64BITS + /* for j in 16 to 63, Xj <- (Sigma_1_512( Xj-2) + Xj-7 + Sigma_0_512(Xj-15) + * + Xj-16 ). */ + if (j >= 16) { + uint64bits_t xj2, xj15; + xj2 = X[(j - 2) & 0xF]; + xj15 = X[(j - 15) & 0xF]; + X[j & 0xF] = (sigma1(xj2) + X[(j - 7) & 0xF] + sigma0(xj15) + X[(j - 16) & 0xF]); + } + t1 = H + sum1(E) + ch(E, F, G) + primeSqrt[j] + X[j & 0xF]; + t2 = sum0(A) + maj(A, B, C); + + /* + H = G ; + G = F; + F = E; + E = D+t1; + D = C; + C = B; + B = A; + A = t1+t2; + */ + H = G; + G = F; + F = E; + E = D; + D = C; + C = B; + B = A; + E += t1; + A = t1 + t2; + +#endif // NATIVE_64BITS? } - t1 = H + sum1(E) + ch(E, F, G) + primeSqrt[j] + X[j & 0xF]; - t2 = sum0(A) + maj(A, B, C); - /* - H = G ; - G = F; - F = E; - E = D+t1; - D = C; - C = B; - B = A; - A = t1+t2; - */ - H = G; - G = F; - F = E; - E = D; - D = C; - C = B; - B = A; - E += t1; - A = t1 + t2; - -#endif // NATIVE_64BITS? - } - - //(update chaining values) (H1 , H2 , H3 , H4 ) <- (H1 + A, H2 + B, H3 + C, H4 - //+ D...) + //(update chaining values) (H1 , H2 , H3 , H4 ) <- (H1 + A, H2 + B, H3 + C, H4 + //+ D...) #ifndef NATIVE_64BITS - ADD64(accumulator[0], A); - ADD64(accumulator[1], B); - ADD64(accumulator[2], C); - ADD64(accumulator[3], D); - ADD64(accumulator[4], E); - ADD64(accumulator[5], F); - ADD64(accumulator[6], G); - ADD64(accumulator[7], H); + ADD64(accumulator[0], A); + ADD64(accumulator[1], B); + ADD64(accumulator[2], C); + ADD64(accumulator[3], D); + ADD64(accumulator[4], E); + ADD64(accumulator[5], F); + ADD64(accumulator[6], G); + ADD64(accumulator[7], H); #else - accumulator[0] += A; - accumulator[1] += B; - accumulator[2] += C; - accumulator[3] += D; - accumulator[4] += E; - accumulator[5] += F; - accumulator[6] += G; - accumulator[7] += H; + accumulator[0] += A; + accumulator[1] += B; + accumulator[2] += C; + accumulator[3] += D; + accumulator[4] += E; + accumulator[5] += F; + accumulator[6] += G; + accumulator[7] += H; #endif } #else void cx_sha512_block(cx_sha512_t *ctx); -#endif //! HAVE_SHA512_WITH_BLOCK_ALT_METHOD - -cx_err_t cx_sha512_update(cx_sha512_t *ctx, const uint8_t *data, size_t len) { - size_t r; - uint8_t block_size; - uint8_t *block; - size_t blen; - - if (ctx == NULL) { - return CX_INVALID_PARAMETER; - } - - if (data == NULL) { - if (len == 0) { - return CX_OK; - } else { - return CX_INVALID_PARAMETER; - } - } - - block_size = 128; - block = ctx->block; - blen = ctx->blen; - ctx->blen = 0; - - // --- append input data and process all blocks --- - if ((blen + len) >= block_size) { - r = block_size - blen; - do { - if (ctx->header.counter == CX_HASH_MAX_BLOCK_COUNT) { +#endif //! HAVE_SHA512_WITH_BLOCK_ALT_METHOD + +cx_err_t cx_sha512_update(cx_sha512_t *ctx, const uint8_t *data, size_t len) +{ + size_t r; + uint8_t block_size; + uint8_t *block; + size_t blen; + + if (ctx == NULL) { return CX_INVALID_PARAMETER; - } - memcpy(block + blen, data, r); - cx_sha512_block(ctx); - blen = 0; - ctx->header.counter++; - data += r; - len -= r; - r = block_size; - } while (len >= block_size); - } - - // --- remind rest data--- - memcpy(block + blen, data, len); - blen += len; - ctx->blen = blen; - return CX_OK; -} + } -cx_err_t cx_sha512_final(cx_sha512_t *ctx, uint8_t *digest) { - uint64_t bitlen; - size_t len; + if (data == NULL) { + if (len == 0) { + return CX_OK; + } + else { + return CX_INVALID_PARAMETER; + } + } - uint8_t * block = ctx->block; - unsigned int blen = ctx->blen; - uint8_t * acc = ctx->acc; + block_size = 128; + block = ctx->block; + blen = ctx->blen; + ctx->blen = 0; + + // --- append input data and process all blocks --- + if ((blen + len) >= block_size) { + r = block_size - blen; + do { + if (ctx->header.counter == CX_HASH_MAX_BLOCK_COUNT) { + return CX_INVALID_PARAMETER; + } + memcpy(block + blen, data, r); + cx_sha512_block(ctx); + blen = 0; + ctx->header.counter++; + data += r; + len -= r; + r = block_size; + } while (len >= block_size); + } - // one more block? - block[blen] = 0x80; - blen++; + // --- remind rest data--- + memcpy(block + blen, data, len); + blen += len; + ctx->blen = blen; + return CX_OK; +} - bitlen = (((uint64_t)ctx->header.counter) * 128UL + (uint64_t)blen - 1UL) * 8UL; - // one more block? - if ((128 - blen) < 16) { +cx_err_t cx_sha512_final(cx_sha512_t *ctx, uint8_t *digest) +{ + uint64_t bitlen; + size_t len; + + uint8_t *block = ctx->block; + unsigned int blen = ctx->blen; + uint8_t *acc = ctx->acc; + + // one more block? + block[blen] = 0x80; + blen++; + + bitlen = (((uint64_t) ctx->header.counter) * 128UL + (uint64_t) blen - 1UL) * 8UL; + // one more block? + if ((128 - blen) < 16) { + memset(block + blen, 0, 128 - blen); + cx_sha512_block(ctx); + blen = 0; + } + // last block! memset(block + blen, 0, 128 - blen); - cx_sha512_block(ctx); - blen = 0; - } - // last block! - memset(block + blen, 0, 128 - blen); #ifdef ARCH_LITTLE_ENDIAN - (*(uint64_t *)(&block[128 - 8])) = cx_swap_uint64(bitlen); + (*(uint64_t *) (&block[128 - 8])) = cx_swap_uint64(bitlen); #else - (*(uint64_t *)(&block[128 - 8])) = bitlen; + (*(uint64_t *) (&block[128 - 8])) = bitlen; #endif - cx_sha512_block(ctx); - // provide result - len = (ctx->header.info->md_type == CX_SHA512) ? 512 >> 3 : 384 >> 3; + cx_sha512_block(ctx); + // provide result + len = (ctx->header.info->md_type == CX_SHA512) ? 512 >> 3 : 384 >> 3; #ifdef ARCH_LITTLE_ENDIAN - cx_swap_buffer64((uint64bits_t *)acc, 8); + cx_swap_buffer64((uint64bits_t *) acc, 8); #endif - memcpy(digest, acc, len); - return CX_OK; + memcpy(digest, acc, len); + return CX_OK; } #if defined(HAVE_SHA512) -size_t cx_hash_sha512(const uint8_t *in, size_t in_len, uint8_t *out, size_t out_len) { - if (out_len < CX_SHA512_SIZE) { - return 0; - } - cx_sha512_init_no_throw(&G_cx.sha512); - cx_sha512_update(&G_cx.sha512, in, in_len); - cx_sha512_final(&G_cx.sha512, out); - explicit_bzero(&G_cx.sha512, sizeof(cx_sha512_t)); - return CX_SHA512_SIZE; +size_t cx_hash_sha512(const uint8_t *in, size_t in_len, uint8_t *out, size_t out_len) +{ + if (out_len < CX_SHA512_SIZE) { + return 0; + } + cx_sha512_init_no_throw(&G_cx.sha512); + cx_sha512_update(&G_cx.sha512, in, in_len); + cx_sha512_final(&G_cx.sha512, out); + explicit_bzero(&G_cx.sha512, sizeof(cx_sha512_t)); + return CX_SHA512_SIZE; } #endif -#endif // defined (HAVE_SHA512) || defined(HAVE_SHA384) +#endif // defined (HAVE_SHA512) || defined(HAVE_SHA384) diff --git a/lib_cxng/src/cx_sha512.h b/lib_cxng/src/cx_sha512.h index bd9173ae1..ee2c2e289 100644 --- a/lib_cxng/src/cx_sha512.h +++ b/lib_cxng/src/cx_sha512.h @@ -9,15 +9,15 @@ #ifdef HAVE_SHA384 extern const cx_hash_info_t cx_sha384_info; -#endif // HAVE_SHA384 +#endif // HAVE_SHA384 #ifdef HAVE_SHA512 extern const cx_hash_info_t cx_sha512_info; -#endif // HAVE_SHA512 +#endif // HAVE_SHA512 cx_err_t cx_sha512_update(cx_sha512_t *ctx, const uint8_t *data, size_t len); cx_err_t cx_sha512_final(cx_sha512_t *ctx, uint8_t *digest); -#endif // CX_SHA512_H +#endif // CX_SHA512_H -#endif // defined(HAVE_SHA512) || defined(HAVE_SHA384) +#endif // defined(HAVE_SHA512) || defined(HAVE_SHA384) diff --git a/lib_cxng/src/cx_utils.c b/lib_cxng/src/cx_utils.c index d95ad067a..3a390d131 100644 --- a/lib_cxng/src/cx_utils.c +++ b/lib_cxng/src/cx_utils.c @@ -1,178 +1,191 @@ /******************************************************************************* -* Ledger Nano S - Secure firmware -* (c) 2022 Ledger -* -* Licensed under the Apache License, Version 2.0 (the "License"); -* you may not use this file except in compliance with the License. -* You may obtain a copy of the License at -* -* http://www.apache.org/licenses/LICENSE-2.0 -* -* Unless required by applicable law or agreed to in writing, software -* distributed under the License is distributed on an "AS IS" BASIS, -* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -* See the License for the specific language governing permissions and -* limitations under the License. -********************************************************************************/ + * Ledger Nano S - Secure firmware + * (c) 2022 Ledger + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT 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 "cx_utils.h" - /* ======================================================================= */ /* 32 BITS manipulation */ /* ======================================================================= */ #ifndef _CX_INLINE_U32 -unsigned long int cx_rotl(unsigned long int x, unsigned char n) { - return (((x) << (n)) | ((x) >> (32 - (n)))); +unsigned long int cx_rotl(unsigned long int x, unsigned char n) +{ + return (((x) << (n)) | ((x) >> (32 - (n)))); } -unsigned long int cx_rotr(unsigned long int x, unsigned char n) { - return (((x) >> (n)) | ((x) << ((32) - (n)))); +unsigned long int cx_rotr(unsigned long int x, unsigned char n) +{ + return (((x) >> (n)) | ((x) << ((32) - (n)))); } -unsigned long int cx_shr(unsigned long int x, unsigned char n) { - return ((x) >> (n)); +unsigned long int cx_shr(unsigned long int x, unsigned char n) +{ + return ((x) >> (n)); } #endif -uint32_t cx_swap_uint32(uint32_t v) { - return (((v) << 24) & 0xFF000000U) | (((v) << 8) & 0x00FF0000U) | (((v) >> 8) & 0x0000FF00U) | - (((v) >> 24) & 0x000000FFU); +uint32_t cx_swap_uint32(uint32_t v) +{ + return (((v) << 24) & 0xFF000000U) | (((v) << 8) & 0x00FF0000U) | (((v) >> 8) & 0x0000FF00U) + | (((v) >> 24) & 0x000000FFU); } -void cx_swap_buffer32(uint32_t *v, size_t len) { - while (len--) { +void cx_swap_buffer32(uint32_t *v, size_t len) +{ + while (len--) { #ifdef ST31 - unsigned int tmp; - tmp = ((unsigned char *)v)[len * 4 + 3]; - ((unsigned char *)v)[len * 4 + 3] = ((unsigned char *)v)[len * 4]; - ((unsigned char *)v)[len * 4] = tmp; - tmp = ((unsigned char *)v)[len * 4 + 2]; - ((unsigned char *)v)[len * 4 + 2] = ((unsigned char *)v)[len * 4 + 1]; - ((unsigned char *)v)[len * 4 + 1] = tmp; + unsigned int tmp; + tmp = ((unsigned char *) v)[len * 4 + 3]; + ((unsigned char *) v)[len * 4 + 3] = ((unsigned char *) v)[len * 4]; + ((unsigned char *) v)[len * 4] = tmp; + tmp = ((unsigned char *) v)[len * 4 + 2]; + ((unsigned char *) v)[len * 4 + 2] = ((unsigned char *) v)[len * 4 + 1]; + ((unsigned char *) v)[len * 4 + 1] = tmp; #else - v[len] = cx_swap_uint32(v[len]); + v[len] = cx_swap_uint32(v[len]); #endif - } + } } /* ======================================================================= */ /* 64 BITS manipulation */ /* ======================================================================= */ -#ifndef NATIVE_64BITS // NO 64BITS -void cx_rotr64(uint64bits_t *x, unsigned int n) { - unsigned long int sl_rot, sh_rot; - if (n >= 32) { - sl_rot = x->l; - x->l = x->h; - x->h = sl_rot; - n -= 32; - } - sh_rot = ((((x->h) & 0xFFFFFFFF) << (32 - n))); - sl_rot = ((((x->l) & 0xFFFFFFFF) << (32 - n))); - // rotate - x->h = ((x->h >> n) | sl_rot); - x->l = ((x->l >> n) | sh_rot); -} -void cx_shr64(uint64bits_t *x, unsigned char n) { - unsigned long int sl_shr; - - if (n >= 32) { - x->l = (x->h); - x->h = 0; - n -= 32; - } - - sl_shr = ((((x->h) & 0xFFFFFFFF) << (32 - n))); - x->l = ((x->l) >> n) | sl_shr; - x->h = ((x->h) >> n); +#ifndef NATIVE_64BITS // NO 64BITS +void cx_rotr64(uint64bits_t *x, unsigned int n) +{ + unsigned long int sl_rot, sh_rot; + if (n >= 32) { + sl_rot = x->l; + x->l = x->h; + x->h = sl_rot; + n -= 32; + } + sh_rot = ((((x->h) & 0xFFFFFFFF) << (32 - n))); + sl_rot = ((((x->l) & 0xFFFFFFFF) << (32 - n))); + // rotate + x->h = ((x->h >> n) | sl_rot); + x->l = ((x->l >> n) | sh_rot); +} +void cx_shr64(uint64bits_t *x, unsigned char n) +{ + unsigned long int sl_shr; + + if (n >= 32) { + x->l = (x->h); + x->h = 0; + n -= 32; + } + + sl_shr = ((((x->h) & 0xFFFFFFFF) << (32 - n))); + x->l = ((x->l) >> n) | sl_shr; + x->h = ((x->h) >> n); } #else #ifndef _CX_INLINE_U64 -uint64bits_t cx_rotr64(uint64bits_t x, unsigned int n) { - return (((x) >> (n)) | ((x) << ((64) - (n)))); +uint64bits_t cx_rotr64(uint64bits_t x, unsigned int n) +{ + return (((x) >> (n)) | ((x) << ((64) - (n)))); } -uint64bits_t cx_rotl64(uint64bits_t x, unsigned int n) { - return (((x) << (n)) | ((x) >> ((64) - (n)))); +uint64bits_t cx_rotl64(uint64bits_t x, unsigned int n) +{ + return (((x) << (n)) | ((x) >> ((64) - (n)))); } -uint64bits_t cx_shr64(uint64bits_t x, unsigned int n) { - return ((x) >> (n)); +uint64bits_t cx_shr64(uint64bits_t x, unsigned int n) +{ + return ((x) >> (n)); } #endif #endif - #ifndef NATIVE_64BITS -void cx_swap_uint64(uint64bits_t *v) { - unsigned long int h, l; - h = v->h; - l = v->l; - l = cx_swap_uint32(l); - h = cx_swap_uint32(h); - v->h = l; - v->l = h; -} -#else // HAVE_SYS_UINT64_SUPPORT -uint64bits_t cx_swap_uint64(uint64bits_t v) { - uint32_t h, l; - h = (uint32_t)((v >> 32) & 0xFFFFFFFF); - l = (uint32_t)(v & 0xFFFFFFFF); - l = cx_swap_uint32(l); - h = cx_swap_uint32(h); - return (((uint64bits_t)l) << 32) | ((uint64bits_t)h); -} -#endif // HAVE_SYS_UINT64_SUPPORT - -void cx_swap_buffer64(uint64bits_t *v, int len) { +void cx_swap_uint64(uint64bits_t *v) +{ + unsigned long int h, l; + h = v->h; + l = v->l; + l = cx_swap_uint32(l); + h = cx_swap_uint32(h); + v->h = l; + v->l = h; +} +#else // HAVE_SYS_UINT64_SUPPORT +uint64bits_t cx_swap_uint64(uint64bits_t v) +{ + uint32_t h, l; + h = (uint32_t) ((v >> 32) & 0xFFFFFFFF); + l = (uint32_t) (v & 0xFFFFFFFF); + l = cx_swap_uint32(l); + h = cx_swap_uint32(h); + return (((uint64bits_t) l) << 32) | ((uint64bits_t) h); +} +#endif // HAVE_SYS_UINT64_SUPPORT + +void cx_swap_buffer64(uint64bits_t *v, int len) +{ #ifndef NATIVE_64BITS - while (len--) { - cx_swap_uint64(&v[len]); - } -#else // HAVE_SYS_UINT64_SUPPORT - uint64bits_t i; - while (len--) { - i = *v; - *v++ = cx_swap_uint64(i); - } -#endif // HAVE_SYS_UINT64_SUPPORT + while (len--) { + cx_swap_uint64(&v[len]); + } +#else // HAVE_SYS_UINT64_SUPPORT + uint64bits_t i; + while (len--) { + i = *v; + *v++ = cx_swap_uint64(i); + } +#endif // HAVE_SYS_UINT64_SUPPORT } #ifndef NATIVE_64BITS -void cx_add_64(uint64bits_t *x, uint64bits_t *y) { - unsigned int carry; - unsigned long int addl; +void cx_add_64(uint64bits_t *x, uint64bits_t *y) +{ + unsigned int carry; + unsigned long int addl; - addl = x->l + y->l; - addl = ~addl; - carry = ((((x->l & y->l) | (x->l & ~y->l & addl) | (~x->l & y->l & addl)) >> 31) & 1); + addl = x->l + y->l; + addl = ~addl; + carry = ((((x->l & y->l) | (x->l & ~y->l & addl) | (~x->l & y->l & addl)) >> 31) & 1); - x->l = x->l + y->l; - x->h = x->h + y->h; - if (carry) { - x->h++; - } + x->l = x->l + y->l; + x->h = x->h + y->h; + if (carry) { + x->h++; + } } #endif - -void cx_memxor(uint8_t *buf1, const uint8_t *buf2, size_t len) { - size_t i; - for (i = 0; i < len; i++) { - buf1[i] ^= buf2[i]; - } +void cx_memxor(uint8_t *buf1, const uint8_t *buf2, size_t len) +{ + size_t i; + for (i = 0; i < len; i++) { + buf1[i] ^= buf2[i]; + } } -uint8_t cx_constant_time_eq(const uint8_t *buf1, uint8_t *buf2, size_t len) { - uint8_t diff; - size_t i; - uint8_t is_eq; - for (diff = 0, i = 0; i < len; i++) { +uint8_t cx_constant_time_eq(const uint8_t *buf1, uint8_t *buf2, size_t len) +{ + uint8_t diff; + size_t i; + uint8_t is_eq; + for (diff = 0, i = 0; i < len; i++) { diff |= buf1[i] ^ buf2[i]; - } - is_eq = ((diff | -diff) >> 7) & 1; - return is_eq; + } + is_eq = ((diff | -diff) >> 7) & 1; + return is_eq; } diff --git a/lib_cxng/src/cx_utils.h b/lib_cxng/src/cx_utils.h index c1ccd54a5..7c805b520 100644 --- a/lib_cxng/src/cx_utils.h +++ b/lib_cxng/src/cx_utils.h @@ -1,20 +1,20 @@ /******************************************************************************* -* Ledger Nano S - Secure firmware -* (c) 2022 Ledger -* -* Licensed under the Apache License, Version 2.0 (the "License"); -* you may not use this file except in compliance with the License. -* You may obtain a copy of the License at -* -* http://www.apache.org/licenses/LICENSE-2.0 -* -* Unless required by applicable law or agreed to in writing, software -* distributed under the License is distributed on an "AS IS" BASIS, -* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -* See the License for the specific language governing permissions and -* limitations under the License. -********************************************************************************/ + * Ledger Nano S - Secure firmware + * (c) 2022 Ledger + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT 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 CX_UTILS_H #define CX_UTILS_H @@ -34,32 +34,35 @@ void cx_swap_buffer32(uint32_t *v, size_t len); #define _CX_INLINE_U32 #define cx_rotl(x, n) (((x) << (n)) | ((x) >> (32 - (n)))) #define cx_rotr(x, n) (((x) >> (n)) | ((x) << (32 - (n)))) -#define cx_shr(x, n) ((x) >> (n)) +#define cx_shr(x, n) ((x) >> (n)) #define htole32(value) ((uint32_t) (value)) - /* ======================================================================= */ /* 64 BITS manipulation */ /* ======================================================================= */ -#ifndef NATIVE_64BITS // NO 64BITS +#ifndef NATIVE_64BITS // NO 64BITS #ifdef ARCH_LITTLE_ENDIAN -#define _64BITS(h, l) \ - { l, h } +#define _64BITS(h, l) \ + { \ + l, h \ + } #else -#define _64BITS(h, l) \ - { h, l } +#define _64BITS(h, l) \ + { \ + h, l \ + } #endif -#define CLR64(x) \ - (x).l = 0; \ - (x).h = 0 +#define CLR64(x) \ + (x).l = 0; \ + (x).h = 0 #define ADD64(x, y) cx_add_64(&(x), &(y)) -#define ASSIGN64(r, x) \ - (r).l = (x).l; \ - (r).h = (x).h +#define ASSIGN64(r, x) \ + (r).l = (x).l; \ + (r).h = (x).h void cx_rotr64(uint64bits_t *x, unsigned char n); diff --git a/lib_nbgl/include/nbgl_debug.h b/lib_nbgl/include/nbgl_debug.h index f5218ea17..7bc812796 100644 --- a/lib_nbgl/include/nbgl_debug.h +++ b/lib_nbgl/include/nbgl_debug.h @@ -11,7 +11,7 @@ extern "C" { #endif -//#define WITH_STDIO 1 +// #define WITH_STDIO 1 /********************* * INCLUDES @@ -51,26 +51,40 @@ extern unsigned long gLogger; **********************/ #ifdef WITH_STDIO extern void mainExit(int exitCode); -#define LOG_DEBUG(__logger,...) {\ - if (gLogger&(1<<__logger)) printf(__VA_ARGS__); \ -} -#define LOG_WARN(__logger,...) printf(__VA_ARGS__) -#define LOG_FATAL(__logger,...) {printf(__VA_ARGS__);mainExit(-1);} +#define LOG_DEBUG(__logger, ...) \ + { \ + if (gLogger & (1 << __logger)) \ + printf(__VA_ARGS__); \ + } +#define LOG_WARN(__logger, ...) printf(__VA_ARGS__) +#define LOG_FATAL(__logger, ...) \ + { \ + printf(__VA_ARGS__); \ + mainExit(-1); \ + } -#else // WITH_STDIO +#else // WITH_STDIO #ifdef NBGL_DEBUG #include -#define LOG_DEBUG(__logger,...) do { PRINTF(__VA_ARGS__); } while(0) -#define LOG_WARN(__logger,...) do { PRINTF(__VA_ARGS__); } while(0) -#define LOG_FATAL(__logger,...) do { PRINTF(__VA_ARGS__); halt(); } while(0) +#define LOG_DEBUG(__logger, ...) \ + do { \ + PRINTF(__VA_ARGS__); \ + } while (0) +#define LOG_WARN(__logger, ...) \ + do { \ + PRINTF(__VA_ARGS__); \ + } while (0) +#define LOG_FATAL(__logger, ...) \ + do { \ + PRINTF(__VA_ARGS__); \ + halt(); \ + } while (0) #else -#define LOG_DEBUG(__logger,...) -#define LOG_WARN(__logger,...) -#define LOG_FATAL(__logger,...) -#endif // NBGL_DEBUG -#endif // WITH_STDIO - - +#define LOG_DEBUG(__logger, ...) +#define LOG_WARN(__logger, ...) +#define LOG_FATAL(__logger, ...) +#endif // NBGL_DEBUG +#endif // WITH_STDIO #ifdef __cplusplus } /* extern "C" */ diff --git a/lib_nbgl/include/nbgl_draw.h b/lib_nbgl/include/nbgl_draw.h index c74d34aa1..0d2792f52 100644 --- a/lib_nbgl/include/nbgl_draw.h +++ b/lib_nbgl/include/nbgl_draw.h @@ -20,9 +20,9 @@ extern "C" { /********************* * DEFINES *********************/ -#define QR_V4_NB_PIX_SIZE 33 // qr V4 number of pixels -#define QR_V10_NB_PIX_SIZE 57 // qr V10 number of pixels -#define QR_MAX_PIX_SIZE QR_V10_NB_PIX_SIZE // we support up to V10 qr code version +#define QR_V4_NB_PIX_SIZE 33 // qr V4 number of pixels +#define QR_V10_NB_PIX_SIZE 57 // qr V10 number of pixels +#define QR_MAX_PIX_SIZE QR_V10_NB_PIX_SIZE // we support up to V10 qr code version /********************** * TYPEDEFS @@ -34,15 +34,25 @@ extern "C" { void nbgl_drawIcon(nbgl_area_t *area, nbgl_color_map_t color_map, const nbgl_icon_details_t *icon); void nbgl_drawRoundedRect(const nbgl_area_t *area, nbgl_radius_t radius, color_t innerColor); -void nbgl_drawRoundedBorderedRect(const nbgl_area_t *area, nbgl_radius_t radius, uint8_t stroke, color_t innerColor, color_t borderColor); -void nbgl_drawText(const nbgl_area_t *area, const char* text, uint16_t textLen, nbgl_font_id_e fontId, color_t fontColor); -void nbgl_drawQrCode(const nbgl_area_t *area, uint8_t version, const char *text, color_t backgroundColor); +void nbgl_drawRoundedBorderedRect(const nbgl_area_t *area, + nbgl_radius_t radius, + uint8_t stroke, + color_t innerColor, + color_t borderColor); +void nbgl_drawText(const nbgl_area_t *area, + const char *text, + uint16_t textLen, + nbgl_font_id_e fontId, + color_t fontColor); +void nbgl_drawQrCode(const nbgl_area_t *area, + uint8_t version, + const char *text, + color_t backgroundColor); /********************** * MACROS **********************/ - #ifdef __cplusplus } /* extern "C" */ #endif diff --git a/lib_nbgl/include/nbgl_fonts.h b/lib_nbgl/include/nbgl_fonts.h index ac29c5e8d..240bd5498 100644 --- a/lib_nbgl/include/nbgl_fonts.h +++ b/lib_nbgl/include/nbgl_fonts.h @@ -19,8 +19,8 @@ extern "C" { /********************* * DEFINES *********************/ -#define PIC_CHAR(x) ((const nbgl_font_character_t *)PIC(x)) -#define PIC_BMP(x) ((uint8_t const *)PIC(x)) +#define PIC_CHAR(x) ((const nbgl_font_character_t *) PIC(x)) +#define PIC_BMP(x) ((uint8_t const *) PIC(x)) /********************** * TYPEDEFS @@ -33,13 +33,13 @@ extern "C" { // WARNING: please DON'T CHANGE the order/values of the fields below! // (otherwise python tools that generate data will need to be modified too) typedef struct { - uint32_t encoding:1; ///< method used to encode bitmap data - uint32_t bitmap_offset:14; ///< offset of this character in chars buffer - uint32_t width:6; ///< width of character in pixels - uint32_t x_min_offset:3; ///< x_min = x_min_offset - uint32_t y_min_offset:3; ///< y_min = (y_min + y_min_offset) * 4 - uint32_t x_max_offset:2; ///< x_max = width - x_max_offset - uint32_t y_max_offset:3; ///< y_max = (height - y_max_offset) * 4 + uint32_t encoding : 1; ///< method used to encode bitmap data + uint32_t bitmap_offset : 14; ///< offset of this character in chars buffer + uint32_t width : 6; ///< width of character in pixels + uint32_t x_min_offset : 3; ///< x_min = x_min_offset + uint32_t y_min_offset : 3; ///< y_min = (y_min + y_min_offset) * 4 + uint32_t x_max_offset : 2; ///< x_max = width - x_max_offset + uint32_t y_max_offset : 3; ///< y_max = (height - y_max_offset) * 4 } nbgl_font_character_t; /** @@ -47,17 +47,20 @@ typedef struct { * */ typedef struct { - uint32_t bitmap_len; ///< Size in bytes of the associated bitmap - uint8_t font_id; ///< ID of the font, from @ref nbgl_font_id_e - uint8_t bpp; ///< number of bits per pixels - uint8_t height; ///< height of all characters in pixels - uint8_t line_height; ///< height of a line for all characters in pixels - uint8_t crop; ///< If false, x_min_offset+y_min_offset=bytes to skip - uint8_t y_min; ///< Most top Y coordinate of any char in the font - uint8_t first_char; ///< ASCII code of the first character in \b bitmap and in \b characters fields - uint8_t last_char; ///< ASCII code of the last character in \b bitmap and in \b characters fields - const nbgl_font_character_t *const characters; ///< array containing definitions of all characters - uint8_t const *bitmap; ///< array containing bitmaps of all characters + uint32_t bitmap_len; ///< Size in bytes of the associated bitmap + uint8_t font_id; ///< ID of the font, from @ref nbgl_font_id_e + uint8_t bpp; ///< number of bits per pixels + uint8_t height; ///< height of all characters in pixels + uint8_t line_height; ///< height of a line for all characters in pixels + uint8_t crop; ///< If false, x_min_offset+y_min_offset=bytes to skip + uint8_t y_min; ///< Most top Y coordinate of any char in the font + uint8_t + first_char; ///< ASCII code of the first character in \b bitmap and in \b characters fields + uint8_t + last_char; ///< ASCII code of the last character in \b bitmap and in \b characters fields + const nbgl_font_character_t + *const characters; ///< array containing definitions of all characters + uint8_t const *bitmap; ///< array containing bitmaps of all characters } nbgl_font_t; #define BAGL_ENCODING_LATIN1 0 @@ -71,82 +74,102 @@ typedef struct { // WARNING: please DON'T CHANGE the order of the fields below! // (otherwise python tools that generate data will need to be modified too) typedef struct { - uint32_t char_unicode:21; ///< plane value from 0 to 16 then 16-bit code. - uint32_t width:6; ///< width of character in pixels - uint32_t x_min_offset:5; ///< x_min = x_min_offset - uint32_t y_min_offset:4; ///< y_min = (y_min + y_min_offset) * 4 - uint32_t x_max_offset:5; ///< x_max = width - x_max_offset - uint32_t y_max_offset:5; ///< y_max = (height - y_max_offset) * 4 - uint32_t encoding:2; ///< method used to encode bitmap data - uint32_t bitmap_offset:16; ///< offset of this character in chars buffer + uint32_t char_unicode : 21; ///< plane value from 0 to 16 then 16-bit code. + uint32_t width : 6; ///< width of character in pixels + uint32_t x_min_offset : 5; ///< x_min = x_min_offset + uint32_t y_min_offset : 4; ///< y_min = (y_min + y_min_offset) * 4 + uint32_t x_max_offset : 5; ///< x_max = width - x_max_offset + uint32_t y_max_offset : 5; ///< y_max = (height - y_max_offset) * 4 + uint32_t encoding : 2; ///< method used to encode bitmap data + uint32_t bitmap_offset : 16; ///< offset of this character in chars buffer } nbgl_font_unicode_character_t; /** * @brief structure defining a unicode font * */ typedef struct { - uint16_t bitmap_len; ///< Size in bytes of all characters bitmaps - uint8_t font_id; ///< ID of the font, from @ref nbgl_font_id_e - uint8_t bpp; ///< Number of bits per pixels, (interpreted as nbgl_bpp_t) - uint8_t height; ///< height of all characters in pixels - uint8_t line_height; ///< height of a line for all characters in pixels - uint8_t crop; ///< If false, x_min_offset+y_min_offset=bytes to skip - uint8_t y_min; ///< Most top Y coordinate of any char in the font + uint16_t bitmap_len; ///< Size in bytes of all characters bitmaps + uint8_t font_id; ///< ID of the font, from @ref nbgl_font_id_e + uint8_t bpp; ///< Number of bits per pixels, (interpreted as nbgl_bpp_t) + uint8_t height; ///< height of all characters in pixels + uint8_t line_height; ///< height of a line for all characters in pixels + uint8_t crop; ///< If false, x_min_offset+y_min_offset=bytes to skip + uint8_t y_min; ///< Most top Y coordinate of any char in the font #if !defined(HAVE_LANGUAGE_PACK) - // When using language packs, those 2 pointers does not exists - const nbgl_font_unicode_character_t * const characters; ///< array containing definitions of all characters - uint8_t const * bitmap; ///< array containing bitmaps of all characters -#endif //!defined(HAVE_LANGUAGE_PACK) + // When using language packs, those 2 pointers does not exists + const nbgl_font_unicode_character_t + *const characters; ///< array containing definitions of all characters + uint8_t const *bitmap; ///< array containing bitmaps of all characters +#endif //! defined(HAVE_LANGUAGE_PACK) } nbgl_font_unicode_t; typedef enum { - BAGL_FONT_INTER_REGULAR_24px, - BAGL_FONT_INTER_SEMIBOLD_24px, - BAGL_FONT_INTER_MEDIUM_32px, - BAGL_FONT_HM_ALPHA_MONO_MEDIUM_32px, - BAGL_FONT_INTER_REGULAR_24px_1bpp, - BAGL_FONT_INTER_SEMIBOLD_24px_1bpp, - BAGL_FONT_INTER_MEDIUM_32px_1bpp, - BAGL_FONT_LAST // MUST ALWAYS BE THE LAST, FOR AUTOMATED INVALID VALUE CHECKS + BAGL_FONT_INTER_REGULAR_24px, + BAGL_FONT_INTER_SEMIBOLD_24px, + BAGL_FONT_INTER_MEDIUM_32px, + BAGL_FONT_HM_ALPHA_MONO_MEDIUM_32px, + BAGL_FONT_INTER_REGULAR_24px_1bpp, + BAGL_FONT_INTER_SEMIBOLD_24px_1bpp, + BAGL_FONT_INTER_MEDIUM_32px_1bpp, + BAGL_FONT_LAST // MUST ALWAYS BE THE LAST, FOR AUTOMATED INVALID VALUE CHECKS } nbgl_font_id_e; typedef struct nbgl_unicode_ctx_s { - const nbgl_font_unicode_t *font; - const nbgl_font_unicode_character_t *characters; - const uint8_t *bitmap; - uint32_t unicode_character_byte_count; + const nbgl_font_unicode_t *font; + const nbgl_font_unicode_character_t *characters; + const uint8_t *bitmap; + uint32_t unicode_character_byte_count; } nbgl_unicode_ctx_t; /********************** * GLOBAL PROTOTYPES **********************/ -const nbgl_font_t* nbgl_font_getFont(unsigned int fontId); +const nbgl_font_t *nbgl_font_getFont(unsigned int fontId); const nbgl_font_t *nbgl_getFont(nbgl_font_id_e fontId); -uint16_t nbgl_getSingleLineTextWidth(nbgl_font_id_e fontId, const char* text); -uint16_t nbgl_getSingleLineTextWidthInLen(nbgl_font_id_e fontId, const char* text, uint16_t maxLen); -uint16_t nbgl_getTextWidth(nbgl_font_id_e fontId, const char* text); -uint8_t nbgl_getCharWidth(nbgl_font_id_e fontId, const char *text); -uint8_t nbgl_getFontHeight(nbgl_font_id_e fontId); -uint8_t nbgl_getFontLineHeight(nbgl_font_id_e fontId); +uint16_t nbgl_getSingleLineTextWidth(nbgl_font_id_e fontId, const char *text); +uint16_t nbgl_getSingleLineTextWidthInLen(nbgl_font_id_e fontId, const char *text, uint16_t maxLen); +uint16_t nbgl_getTextWidth(nbgl_font_id_e fontId, const char *text); +uint8_t nbgl_getCharWidth(nbgl_font_id_e fontId, const char *text); +uint8_t nbgl_getFontHeight(nbgl_font_id_e fontId); +uint8_t nbgl_getFontLineHeight(nbgl_font_id_e fontId); uint16_t nbgl_getTextNbLines(const char *text); -uint16_t nbgl_getTextHeight(nbgl_font_id_e fontId, const char*text); -uint16_t nbgl_getTextLength(const char*text); -void nbgl_getTextMaxLenAndWidth(nbgl_font_id_e fontId, const char* text, uint16_t maxWidth, uint16_t *len, uint16_t *width, bool wrapping); -uint16_t nbgl_getTextNbLinesInWidth(nbgl_font_id_e fontId, const char* text, uint16_t maxWidth, bool wrapping); -uint16_t nbgl_getTextHeightInWidth(nbgl_font_id_e fontId, const char*text, uint16_t maxWidth, bool wrapping); -bool nbgl_getTextMaxLenAndWidthFromEnd(nbgl_font_id_e fontId, const char* text, uint16_t maxWidth, uint16_t *len, uint16_t *width); -bool nbgl_getTextMaxLenInNbLines(nbgl_font_id_e fontId, const char* text, uint16_t maxWidth, uint16_t maxNbLines, uint16_t *len); -void nbgl_textWrapOnNbLines(nbgl_font_id_e fontId, char* text, uint16_t maxWidth, uint8_t nbLines); +uint16_t nbgl_getTextHeight(nbgl_font_id_e fontId, const char *text); +uint16_t nbgl_getTextLength(const char *text); +void nbgl_getTextMaxLenAndWidth(nbgl_font_id_e fontId, + const char *text, + uint16_t maxWidth, + uint16_t *len, + uint16_t *width, + bool wrapping); +uint16_t nbgl_getTextNbLinesInWidth(nbgl_font_id_e fontId, + const char *text, + uint16_t maxWidth, + bool wrapping); +uint16_t nbgl_getTextHeightInWidth(nbgl_font_id_e fontId, + const char *text, + uint16_t maxWidth, + bool wrapping); +bool nbgl_getTextMaxLenAndWidthFromEnd(nbgl_font_id_e fontId, + const char *text, + uint16_t maxWidth, + uint16_t *len, + uint16_t *width); +bool nbgl_getTextMaxLenInNbLines(nbgl_font_id_e fontId, + const char *text, + uint16_t maxWidth, + uint16_t maxNbLines, + uint16_t *len); +void nbgl_textWrapOnNbLines(nbgl_font_id_e fontId, char *text, uint16_t maxWidth, uint8_t nbLines); uint32_t nbgl_popUnicodeChar(const uint8_t **text, uint16_t *text_length, bool *is_unicode); #ifdef HAVE_UNICODE_SUPPORT -nbgl_unicode_ctx_t* nbgl_getUnicodeFont(nbgl_font_id_e font_id); +nbgl_unicode_ctx_t *nbgl_getUnicodeFont(nbgl_font_id_e font_id); const nbgl_font_unicode_character_t *nbgl_getUnicodeFontCharacter(uint32_t unicode); -uint32_t nbgl_getUnicodeFontCharacterByteCount(void); +uint32_t nbgl_getUnicodeFontCharacterByteCount(void); #ifdef HAVE_LANGUAGE_PACK void nbgl_refreshUnicodeFont(void); #endif -#endif // HAVE_UNICODE_SUPPORT +#endif // HAVE_UNICODE_SUPPORT /********************** * MACROS diff --git a/lib_nbgl/include/nbgl_front.h b/lib_nbgl/include/nbgl_front.h index 5f792506a..08ed39345 100644 --- a/lib_nbgl/include/nbgl_front.h +++ b/lib_nbgl/include/nbgl_front.h @@ -29,16 +29,27 @@ extern "C" { **********************/ void nbgl_frontDrawRect(const nbgl_area_t *area); void nbgl_frontDrawHorizontalLine(const nbgl_area_t *area, uint8_t mask, color_t lineColor); -void nbgl_frontDrawImage(const nbgl_area_t *area, const uint8_t* buffer, nbgl_transformation_t transformation, nbgl_color_map_t colorMap); -void nbgl_frontDrawImageFile(const nbgl_area_t *area, const uint8_t* buffer, nbgl_color_map_t colorMap, const uint8_t *uzlib_chunk_buffer); -void nbgl_frontDrawImageRle(const nbgl_area_t *area, const uint8_t *buffer, uint32_t buffer_len, color_t fore_color, uint8_t nb_skipped_bytes); -void nbgl_frontRefreshArea(const nbgl_area_t * area, nbgl_refresh_mode_t mode, nbgl_post_refresh_t post_refresh); +void nbgl_frontDrawImage(const nbgl_area_t *area, + const uint8_t *buffer, + nbgl_transformation_t transformation, + nbgl_color_map_t colorMap); +void nbgl_frontDrawImageFile(const nbgl_area_t *area, + const uint8_t *buffer, + nbgl_color_map_t colorMap, + const uint8_t *uzlib_chunk_buffer); +void nbgl_frontDrawImageRle(const nbgl_area_t *area, + const uint8_t *buffer, + uint32_t buffer_len, + color_t fore_color, + uint8_t nb_skipped_bytes); +void nbgl_frontRefreshArea(const nbgl_area_t *area, + nbgl_refresh_mode_t mode, + nbgl_post_refresh_t post_refresh); /********************** * MACROS **********************/ - #ifdef __cplusplus } /* extern "C" */ #endif diff --git a/lib_nbgl/include/nbgl_image_utils.h b/lib_nbgl/include/nbgl_image_utils.h index b714bd7cc..0c951b059 100644 --- a/lib_nbgl/include/nbgl_image_utils.h +++ b/lib_nbgl/include/nbgl_image_utils.h @@ -22,29 +22,29 @@ extern "C" { /** * Width offset in image file */ -#define WIDTH_OFFSET 0 +#define WIDTH_OFFSET 0 /** * Height offset in image file */ -#define HEIGHT_OFFSET 2 +#define HEIGHT_OFFSET 2 /** * BPP & Compression offset in image file */ -#define BPP_COMPRESS_OFFSET 4 +#define BPP_COMPRESS_OFFSET 4 /** * Buffer length offset in image file * */ -#define BUFFER_LEN_OFFSET 5 +#define BUFFER_LEN_OFFSET 5 /** * Buffer offset in image file * */ -#define BUFFER_OFFSET 8 +#define BUFFER_OFFSET 8 /** * Size in bytes of an image file header @@ -59,33 +59,35 @@ extern "C" { * @brief macro to get the width of the image file * @param image_file uint8_t* buffer representing the image file */ -#define GET_IMAGE_FILE_WIDTH(image_file) (image_file[WIDTH_OFFSET] | (image_file[WIDTH_OFFSET+1]<<8)) +#define GET_IMAGE_FILE_WIDTH(image_file) \ + (image_file[WIDTH_OFFSET] | (image_file[WIDTH_OFFSET + 1] << 8)) /** * @brief macro to get the height of the image file * @param image_file uint8_t* buffer representing the image file */ -#define GET_IMAGE_FILE_HEIGHT(image_file) (image_file[HEIGHT_OFFSET] | (image_file[HEIGHT_OFFSET+1]<<8)) +#define GET_IMAGE_FILE_HEIGHT(image_file) \ + (image_file[HEIGHT_OFFSET] | (image_file[HEIGHT_OFFSET + 1] << 8)) /** * @brief macro to get the bpp of the image file * @param image_file uint8_t* buffer representing the image file */ -#define GET_IMAGE_FILE_BPP(image_file) (image_file[BPP_COMPRESS_OFFSET]>>4) +#define GET_IMAGE_FILE_BPP(image_file) (image_file[BPP_COMPRESS_OFFSET] >> 4) /** * @brief macro to get the compression of the image file * @param image_file uint8_t* buffer representing the image file */ -#define GET_IMAGE_FILE_COMPRESSION(image_file) (image_file[BPP_COMPRESS_OFFSET]&0xF) +#define GET_IMAGE_FILE_COMPRESSION(image_file) (image_file[BPP_COMPRESS_OFFSET] & 0xF) /** * @brief macro to get the buffer len of the image file * @param image_file uint8_t* buffer representing the image file */ -#define GET_IMAGE_FILE_BUFFER_LEN(image_file) (image_file[BUFFER_LEN_OFFSET] \ - | (image_file[BUFFER_LEN_OFFSET+1]<<8) \ - | (image_file[BUFFER_LEN_OFFSET+2]<<16)) +#define GET_IMAGE_FILE_BUFFER_LEN(image_file) \ + (image_file[BUFFER_LEN_OFFSET] | (image_file[BUFFER_LEN_OFFSET + 1] << 8) \ + | (image_file[BUFFER_LEN_OFFSET + 2] << 16)) /** * @brief macro to get the buffer of the image file @@ -93,7 +95,6 @@ extern "C" { */ #define GET_IMAGE_FILE_BUFFER(image_file) (&image_file[BUFFER_OFFSET]) - #ifdef __cplusplus } /* extern "C" */ #endif diff --git a/lib_nbgl/include/nbgl_layout.h b/lib_nbgl/include/nbgl_layout.h index a3a5eb39f..98908a004 100644 --- a/lib_nbgl/include/nbgl_layout.h +++ b/lib_nbgl/include/nbgl_layout.h @@ -20,12 +20,11 @@ extern "C" { * INCLUDES *********************/ - /********************* * DEFINES *********************/ #define NO_MORE_OBJ_ERROR -3 -#define NBGL_NO_TUNE NB_TUNES +#define NBGL_NO_TUNE NB_TUNES #define NB_MAX_SUGGESTION_BUTTONS 4 @@ -36,16 +35,16 @@ extern "C" { /** * @brief prototype of function to be called an object is touched * @param token integer passed when registering callback - * @param index when the object touched is a list of radio buttons, gives the index of the activated button + * @param index when the object touched is a list of radio buttons, gives the index of the activated + * button */ typedef void (*nbgl_layoutTouchCallback_t)(int token, uint8_t index); - /** * @brief type shared externally * */ -typedef void* nbgl_layout_t; +typedef void *nbgl_layout_t; /** * @brief This structure contains info to build a navigation bar at the bottom of the screen @@ -53,57 +52,66 @@ typedef void* nbgl_layout_t; * */ typedef struct { - uint8_t token; ///< the token that will be used as argument of the callback - uint8_t nbPages; ///< number of pages. (if 0, no navigation) - uint8_t activePage; ///< index of active page (from 0 to nbPages-1). - bool withExitKey; ///< if set to true, an exit button is drawn, either on the left of navigation keys or in the center if no navigation - bool withSeparationLine; ///< if set to true, an horizontal line is drawn on top of bar in light gray - tune_index_e tuneId; ///< if not @ref NBGL_NO_TUNE, a tune will be played when pressing keys) + uint8_t token; ///< the token that will be used as argument of the callback + uint8_t nbPages; ///< number of pages. (if 0, no navigation) + uint8_t activePage; ///< index of active page (from 0 to nbPages-1). + bool withExitKey; ///< if set to true, an exit button is drawn, either on the left of + ///< navigation keys or in the center if no navigation + bool withSeparationLine; ///< if set to true, an horizontal line is drawn on top of bar in + ///< light gray + tune_index_e tuneId; ///< if not @ref NBGL_NO_TUNE, a tune will be played when pressing keys) } nbgl_layoutNavigationBar_t; - /** - * @brief Structure containing all information when creating a layout. This structure must be passed as argument to @ref nbgl_layoutGet + * @brief Structure containing all information when creating a layout. This structure must be passed + * as argument to @ref nbgl_layoutGet * @note It shall not be used * */ typedef struct nbgl_layoutDescription_s { - bool modal; ///< if true, puts the layout on top of screen stack (modal). Otherwise puts on background (for apps) - bool withLeftBorder; ///< if true, draws a light gray left border on the whole height of the screen - const char *tapActionText; ///< Light gray text used when main container is "tapable" - uint8_t tapActionToken; ///< the token that will be used as argument of the onActionCallback when main container is "tapped" - tune_index_e tapTuneId; ///< if not @ref NBGL_NO_TUNE, a tune will be played when tapping on main container - nbgl_layoutTouchCallback_t onActionCallback; ///< the callback to be called on any action on the layout - nbgl_screenTickerConfiguration_t ticker; // configuration of ticker (timeout) + bool modal; ///< if true, puts the layout on top of screen stack (modal). Otherwise puts on + ///< background (for apps) + bool withLeftBorder; ///< if true, draws a light gray left border on the whole height of the + ///< screen + const char *tapActionText; ///< Light gray text used when main container is "tapable" + uint8_t tapActionToken; ///< the token that will be used as argument of the onActionCallback + ///< when main container is "tapped" + tune_index_e tapTuneId; ///< if not @ref NBGL_NO_TUNE, a tune will be played when tapping on + ///< main container + nbgl_layoutTouchCallback_t + onActionCallback; ///< the callback to be called on any action on the layout + nbgl_screenTickerConfiguration_t ticker; // configuration of ticker (timeout) } nbgl_layoutDescription_t; - /** * @brief This structure contains info to build a clickable "bar" with a text and an icon * */ typedef struct { - const nbgl_icon_details_t *iconLeft; ///< a buffer containing the 1BPP icon for icon on left (can be NULL) - const char *text; ///< text (can be NULL) - const nbgl_icon_details_t *iconRight; ///< a buffer containing the 1BPP icon for icon 2 (can be NULL). Dimensions must be the same as iconLeft - const char *subText; ///< sub text (can be NULL) - uint8_t token; ///< the token that will be used as argument of the callback - bool inactive; ///< if set to true, the bar is grayed-out and cannot be touched - bool centered; ///< if set to true, the text is centered horizontaly in the bar - tune_index_e tuneId; ///< if not @ref NBGL_NO_TUNE, a tune will be played + const nbgl_icon_details_t + *iconLeft; ///< a buffer containing the 1BPP icon for icon on left (can be NULL) + const char *text; ///< text (can be NULL) + const nbgl_icon_details_t *iconRight; ///< a buffer containing the 1BPP icon for icon 2 (can be + ///< NULL). Dimensions must be the same as iconLeft + const char *subText; ///< sub text (can be NULL) + uint8_t token; ///< the token that will be used as argument of the callback + bool inactive; ///< if set to true, the bar is grayed-out and cannot be touched + bool centered; ///< if set to true, the text is centered horizontaly in the bar + tune_index_e tuneId; ///< if not @ref NBGL_NO_TUNE, a tune will be played } nbgl_layoutBar_t; /** - * @brief This structure contains info to build a switch (on the right) with a description (on the left), with a - * potential sub-description (in gray) + * @brief This structure contains info to build a switch (on the right) with a description (on the + * left), with a potential sub-description (in gray) * */ typedef struct { - const char *text; ///< main text for the switch - const char *subText; ///< description under main text (NULL terminated, single line, may be null) - nbgl_state_t initState; ///< initial state of the switch - uint8_t token; ///< the token that will be used as argument of the callback - tune_index_e tuneId; ///< if not @ref NBGL_NO_TUNE, a tune will be played + const char *text; ///< main text for the switch + const char + *subText; ///< description under main text (NULL terminated, single line, may be null) + nbgl_state_t initState; ///< initial state of the switch + uint8_t token; ///< the token that will be used as argument of the callback + tune_index_e tuneId; ///< if not @ref NBGL_NO_TUNE, a tune will be played } nbgl_layoutSwitch_t; /** @@ -113,25 +121,27 @@ typedef struct { */ typedef struct { union { - const char * const *names; ///< array of strings giving the choices (nbChoices) + const char *const *names; ///< array of strings giving the choices (nbChoices) #if defined(HAVE_LANGUAGE_PACK) - UX_LOC_STRINGS_INDEX *nameIds; ///< array of string Ids giving the choices (nbChoices) -#endif // HAVE_LANGUAGE_PACK + UX_LOC_STRINGS_INDEX *nameIds; ///< array of string Ids giving the choices (nbChoices) +#endif // HAVE_LANGUAGE_PACK }; - bool localized; ///< if set to true, use nameIds and not names - uint8_t nbChoices; ///< number of choices - uint8_t initChoice; ///< index of the current choice - uint8_t token; ///< the token that will be used as argument of the callback - tune_index_e tuneId; ///< if not @ref NBGL_NO_TUNE, a tune will be played when selecting a radio button) + bool localized; ///< if set to true, use nameIds and not names + uint8_t nbChoices; ///< number of choices + uint8_t initChoice; ///< index of the current choice + uint8_t token; ///< the token that will be used as argument of the callback + tune_index_e + tuneId; ///< if not @ref NBGL_NO_TUNE, a tune will be played when selecting a radio button) } nbgl_layoutRadioChoice_t; /** * @brief This structure contains a [tag,value] pair */ typedef struct { - const char *item; ///< string giving the tag name - const char *value; ///< string giving the value name - const nbgl_icon_details_t *valueIcon; ///< a buffer containing the 32px 1BPP icon for icon on right of value (can be NULL) + const char *item; ///< string giving the tag name + const char *value; ///< string giving the value name + const nbgl_icon_details_t *valueIcon; ///< a buffer containing the 32px 1BPP icon for icon on + ///< right of value (can be NULL) } nbgl_layoutTagValue_t; /** @@ -139,60 +149,69 @@ typedef struct { * @param pairIndex index of the tag/value pair to retrieve (from 0 (to nbPairs-1)) * @return a pointer on a static tag/value pair */ -typedef nbgl_layoutTagValue_t* (*nbgl_tagValueCallback_t)(uint8_t pairIndex); - +typedef nbgl_layoutTagValue_t *(*nbgl_tagValueCallback_t)(uint8_t pairIndex); /** * @brief This structure contains a list of [tag,value] pairs */ typedef struct { - nbgl_layoutTagValue_t *pairs; ///< array of [tag,value] pairs (nbPairs items). If NULL, callback is used instead - nbgl_tagValueCallback_t callback; ///< function to call to retrieve a given pair - uint8_t nbPairs; ///< number of pairs in pairs array (or max number of pairs to retrieve with callback) - uint8_t startIndex; ///< index of the first pair to get with callback - uint8_t nbMaxLinesForValue; ///< if > 0, set the max number of lines for value field. And the last line is ended with "..." instead of the 3 last chars - uint8_t token; ///< the token that will be used as argument of the callback if icon in any tag/value pair is touched (index is the index of the pair in pairs[]) - bool smallCaseForValue; ///< if set to true, a 24px font is used for value text, otherwise a 32px font is used - bool wrapping; ///< if set to true, value text will be wrapped on ' ' to avoid cutting words + nbgl_layoutTagValue_t + *pairs; ///< array of [tag,value] pairs (nbPairs items). If NULL, callback is used instead + nbgl_tagValueCallback_t callback; ///< function to call to retrieve a given pair + uint8_t nbPairs; ///< number of pairs in pairs array (or max number of pairs to retrieve with + ///< callback) + uint8_t startIndex; ///< index of the first pair to get with callback + uint8_t nbMaxLinesForValue; ///< if > 0, set the max number of lines for value field. And the + ///< last line is ended with "..." instead of the 3 last chars + uint8_t token; ///< the token that will be used as argument of the callback if icon in any + ///< tag/value pair is touched (index is the index of the pair in pairs[]) + bool smallCaseForValue; ///< if set to true, a 24px font is used for value text, otherwise a + ///< 32px font is used + bool wrapping; ///< if set to true, value text will be wrapped on ' ' to avoid cutting words } nbgl_layoutTagValueList_t; /** * @brief possible styles for Centered Info Area * */ -typedef enum { - LARGE_CASE_INFO, ///< text in BLACK and large case (INTER 32px), subText in black in Inter24px - LARGE_CASE_BOLD_INFO, ///< text in BLACK and large case (INTER 32px), subText in black bold Inter24px, text3 in black Inter24px - LEDGER_INFO, ///< only text, in BLACK and upper case (HM ALPHA MONO), with Ledger border - NORMAL_INFO, ///< Icon in black, a potential text in black bold 24px under it, a potential text in dark gray (24px) under it, a potential text in black (24px) under it - PLUGIN_INFO ///< A potential text in black 32px, a potential text in black (24px) under it, a small horizontal line under it, a potential icon under it, a potential text in black (24px) under it +typedef enum { + LARGE_CASE_INFO, ///< text in BLACK and large case (INTER 32px), subText in black in Inter24px + LARGE_CASE_BOLD_INFO, ///< text in BLACK and large case (INTER 32px), subText in black bold + ///< Inter24px, text3 in black Inter24px + LEDGER_INFO, ///< only text, in BLACK and upper case (HM ALPHA MONO), with Ledger border + NORMAL_INFO, ///< Icon in black, a potential text in black bold 24px under it, a potential text + ///< in dark gray (24px) under it, a potential text in black (24px) under it + PLUGIN_INFO ///< A potential text in black 32px, a potential text in black (24px) under it, a + ///< small horizontal line under it, a potential icon under it, a potential text in + ///< black (24px) under it } nbgl_centeredInfoStyle_t; /** - * @brief This structure contains info to build a centered (vertically and horizontally) area, with a possible Icon, - * a possible text under it, and a possible sub-text gray under it. + * @brief This structure contains info to build a centered (vertically and horizontally) area, with + * a possible Icon, a possible text under it, and a possible sub-text gray under it. * */ typedef struct { - const char *text1; ///< first text (can be null) - const char *text2; ///< second text (can be null) - const char *text3; ///< third text (can be null) - const nbgl_icon_details_t *icon; ///< a buffer containing the 1BPP icon - bool onTop; ///< if set to true, align only horizontaly - nbgl_centeredInfoStyle_t style; ///< style to apply to this info - int16_t offsetY; ///< vertical shift to apply to this info (if >0, shift to bottom) + const char *text1; ///< first text (can be null) + const char *text2; ///< second text (can be null) + const char *text3; ///< third text (can be null) + const nbgl_icon_details_t *icon; ///< a buffer containing the 1BPP icon + bool onTop; ///< if set to true, align only horizontaly + nbgl_centeredInfoStyle_t style; ///< style to apply to this info + int16_t offsetY; ///< vertical shift to apply to this info (if >0, shift to bottom) } nbgl_layoutCenteredInfo_t; /** - * @brief This structure contains info to build a centered (vertically and horizontally) area, with a QR Code, - * a possible text (black, bold) under it, and a possible sub-text (black, regular) under it. + * @brief This structure contains info to build a centered (vertically and horizontally) area, with + * a QR Code, a possible text (black, bold) under it, and a possible sub-text (black, regular) under + * it. * */ typedef struct { - const char *url; ///< URL for QR code - const char *text1; ///< first text (can be null) - const char *text2; ///< second text (can be null) - bool largeText1; ///< if set to true, use 32px font for text1 + const char *url; ///< URL for QR code + const char *text1; ///< first text (can be null) + const char *text2; ///< second text (can be null) + bool largeText1; ///< if set to true, use 32px font for text1 } nbgl_layoutQRCode_t; /** @@ -200,22 +219,23 @@ typedef struct { * */ typedef enum { - ROUNDED_AND_FOOTER_STYLE = 0, ///< A rounded black background full width button on top of a footer - BOTH_ROUNDED_STYLE ///< A rounded black background full width button on top of a rounded white background full width button + ROUNDED_AND_FOOTER_STYLE + = 0, ///< A rounded black background full width button on top of a footer + BOTH_ROUNDED_STYLE ///< A rounded black background full width button on top of a rounded white + ///< background full width button } nbgl_layoutChoiceButtonsStyle_t; - /** * @brief This structure contains info to build a pair of buttons, one on top of the other. * * @note the pair of button is automatically put on bottom of screen */ typedef struct { - const char *topText; ///< up-button text (index 0) - const char *bottomText; ///< bottom-button text (index 1) - uint8_t token; ///< the token that will be used as argument of the callback - nbgl_layoutChoiceButtonsStyle_t style; ///< the style of the pair - tune_index_e tuneId; ///< if not @ref NBGL_NO_TUNE, a tune will be played + const char *topText; ///< up-button text (index 0) + const char *bottomText; ///< bottom-button text (index 1) + uint8_t token; ///< the token that will be used as argument of the callback + nbgl_layoutChoiceButtonsStyle_t style; ///< the style of the pair + tune_index_e tuneId; ///< if not @ref NBGL_NO_TUNE, a tune will be played } nbgl_layoutChoiceButtons_t; /** @@ -223,46 +243,50 @@ typedef struct { * */ typedef enum { - BLACK_BACKGROUND = 0, ///< rounded bordered button, with text/icon in white, on black background - WHITE_BACKGROUND, ///< rounded bordered button, with text/icon in black, on white background - NO_BORDER, ///< simple clickable text, in black - LONG_PRESS ///< long press button, with progress indicator + BLACK_BACKGROUND + = 0, ///< rounded bordered button, with text/icon in white, on black background + WHITE_BACKGROUND, ///< rounded bordered button, with text/icon in black, on white background + NO_BORDER, ///< simple clickable text, in black + LONG_PRESS ///< long press button, with progress indicator } nbgl_layoutButtonStyle_t; /** * @brief This structure contains info to build a single button */ typedef struct { - const char *text; ///< button text - const nbgl_icon_details_t *icon; ///< a buffer containing the 1BPP icon for button1 - uint8_t token; ///< the token that will be used as argument of the callback - nbgl_layoutButtonStyle_t style; - bool fittingContent; ///< if set to true, fit the width of button to text, otherwise full width - bool onBottom; ///< if set to true, align on bottom of page, otherwise put on bottom of previous object - tune_index_e tuneId; ///< if not @ref NBGL_NO_TUNE, a tune will be played + const char *text; ///< button text + const nbgl_icon_details_t *icon; ///< a buffer containing the 1BPP icon for button1 + uint8_t token; ///< the token that will be used as argument of the callback + nbgl_layoutButtonStyle_t style; + bool fittingContent; ///< if set to true, fit the width of button to text, otherwise full width + bool onBottom; ///< if set to true, align on bottom of page, otherwise put on bottom of + ///< previous object + tune_index_e tuneId; ///< if not @ref NBGL_NO_TUNE, a tune will be played } nbgl_layoutButton_t; /** - * @brief This structure contains info to build a progress bar with info. The progress bar itself is 120px width * 12px height + * @brief This structure contains info to build a progress bar with info. The progress bar itself is + * 120px width * 12px height * */ typedef struct { - uint8_t percentage; ///< percentage of completion, from 0 to 100. - const char *text; ///< text in black, on top of progress bar - const char *subText; ///< text in gray, under progress bar + uint8_t percentage; ///< percentage of completion, from 0 to 100. + const char *text; ///< text in black, on top of progress bar + const char *subText; ///< text in gray, under progress bar } nbgl_layoutProgressBar_t; - /** * @brief This structure contains info to build a keyboard with @ref nbgl_layoutAddKeyboard() * */ typedef struct { - bool lettersOnly; ///< if true, only display letter keys and Backspace - keyboardCase_t casing; ///< keyboard casing mode (lower, upper once or upper locked) - keyboardMode_t mode; ///< keyboard mode to start with - uint32_t keyMask; ///< mask used to disable some keys in letters only mod. The 26 LSB bits of mask are used, for the 26 letters of a QWERTY keyboard. Bit[0] for Q, Bit[1] for W and so on - keyboardCallback_t callback; ///< function called when an active key is pressed + bool lettersOnly; ///< if true, only display letter keys and Backspace + keyboardCase_t casing; ///< keyboard casing mode (lower, upper once or upper locked) + keyboardMode_t mode; ///< keyboard mode to start with + uint32_t keyMask; ///< mask used to disable some keys in letters only mod. The 26 LSB bits of + ///< mask are used, for the 26 letters of a QWERTY keyboard. Bit[0] for Q, + ///< Bit[1] for W and so on + keyboardCallback_t callback; ///< function called when an active key is pressed } nbgl_layoutKbd_t; /********************** @@ -270,7 +294,10 @@ typedef struct { **********************/ nbgl_layout_t *nbgl_layoutGet(const nbgl_layoutDescription_t *description); -int nbgl_layoutAddTopRightButton(nbgl_layout_t *layout, const nbgl_icon_details_t *icon, uint8_t token, tune_index_e tuneId); +int nbgl_layoutAddTopRightButton(nbgl_layout_t *layout, + const nbgl_icon_details_t *icon, + uint8_t token, + tune_index_e tuneId); int nbgl_layoutAddTouchableBar(nbgl_layout_t *layout, const nbgl_layoutBar_t *barLayout); int nbgl_layoutAddSwitch(nbgl_layout_t *layout, const nbgl_layoutSwitch_t *switchLayout); int nbgl_layoutAddText(nbgl_layout_t *layout, const char *text, const char *subText); @@ -284,37 +311,87 @@ int nbgl_layoutAddLargeCaseText(nbgl_layout_t *layout, const char *text); int nbgl_layoutAddSeparationLine(nbgl_layout_t *layout); int nbgl_layoutAddButton(nbgl_layout_t *layout, const nbgl_layoutButton_t *buttonInfo); -int nbgl_layoutAddLongPressButton(nbgl_layout_t *layout, const char *text, uint8_t token, tune_index_e tuneId); -int nbgl_layoutAddFooter(nbgl_layout_t *layout, const char *text, uint8_t token, tune_index_e tuneId); -int nbgl_layoutAddSplitFooter(nbgl_layout_t *layout, const char *leftText, uint8_t leftToken, const char *rightText, uint8_t rightToken, tune_index_e tuneId); +int nbgl_layoutAddLongPressButton(nbgl_layout_t *layout, + const char *text, + uint8_t token, + tune_index_e tuneId); +int nbgl_layoutAddFooter(nbgl_layout_t *layout, + const char *text, + uint8_t token, + tune_index_e tuneId); +int nbgl_layoutAddSplitFooter(nbgl_layout_t *layout, + const char *leftText, + uint8_t leftToken, + const char *rightText, + uint8_t rightToken, + tune_index_e tuneId); int nbgl_layoutAddNavigationBar(nbgl_layout_t *layout, const nbgl_layoutNavigationBar_t *info); -int nbgl_layoutAddBottomButton(nbgl_layout_t *layout, const nbgl_icon_details_t *icon, uint8_t token, bool separationLine, tune_index_e tuneId); -int nbgl_layoutAddProgressIndicator(nbgl_layout_t *layout, uint8_t activePage, uint8_t nbPages, bool withBack, uint8_t backToken, tune_index_e tuneId); +int nbgl_layoutAddBottomButton(nbgl_layout_t *layout, + const nbgl_icon_details_t *icon, + uint8_t token, + bool separationLine, + tune_index_e tuneId); +int nbgl_layoutAddProgressIndicator(nbgl_layout_t *layout, + uint8_t activePage, + uint8_t nbPages, + bool withBack, + uint8_t backToken, + tune_index_e tuneId); int nbgl_layoutAddSpinner(nbgl_layout_t *layout, const char *text, bool fixed); #ifdef NBGL_KEYBOARD /* layout objects for page with keyboard */ -int nbgl_layoutAddKeyboard(nbgl_layout_t *layout, const nbgl_layoutKbd_t *kbdInfo); -int nbgl_layoutUpdateKeyboard(nbgl_layout_t *layout, uint8_t index, uint32_t keyMask, bool updateCasing, keyboardCase_t casing); +int nbgl_layoutAddKeyboard(nbgl_layout_t *layout, const nbgl_layoutKbd_t *kbdInfo); +int nbgl_layoutUpdateKeyboard(nbgl_layout_t *layout, + uint8_t index, + uint32_t keyMask, + bool updateCasing, + keyboardCase_t casing); bool nbgl_layoutKeyboardNeedsRefresh(nbgl_layout_t *layout, uint8_t index); -int nbgl_layoutAddSuggestionButtons(nbgl_layout_t *layout, uint8_t nbUsedButtons, - const char *buttonTexts[NB_MAX_SUGGESTION_BUTTONS], - int firstButtonToken, tune_index_e tuneId); -int nbgl_layoutUpdateSuggestionButtons(nbgl_layout_t *layout, uint8_t index, uint8_t nbUsedButtons, - const char *buttonTexts[NB_MAX_SUGGESTION_BUTTONS]); -int nbgl_layoutAddEnteredText(nbgl_layout_t *layout, bool numbered, uint8_t number, const char *text, bool grayedOut, int offsetY, int token); -int nbgl_layoutUpdateEnteredText(nbgl_layout_t *layout, uint8_t index, bool numbered, uint8_t number, const char *text, bool grayedOut); -int nbgl_layoutAddConfirmationButton(nbgl_layout_t *layout, bool active, const char *text, int token, tune_index_e tuneId); -int nbgl_layoutUpdateConfirmationButton(nbgl_layout_t *layout, uint8_t index, bool active, const char *text); -#endif // NBGL_KEYBOARD +int nbgl_layoutAddSuggestionButtons(nbgl_layout_t *layout, + uint8_t nbUsedButtons, + const char *buttonTexts[NB_MAX_SUGGESTION_BUTTONS], + int firstButtonToken, + tune_index_e tuneId); +int nbgl_layoutUpdateSuggestionButtons(nbgl_layout_t *layout, + uint8_t index, + uint8_t nbUsedButtons, + const char *buttonTexts[NB_MAX_SUGGESTION_BUTTONS]); +int nbgl_layoutAddEnteredText(nbgl_layout_t *layout, + bool numbered, + uint8_t number, + const char *text, + bool grayedOut, + int offsetY, + int token); +int nbgl_layoutUpdateEnteredText(nbgl_layout_t *layout, + uint8_t index, + bool numbered, + uint8_t number, + const char *text, + bool grayedOut); +int nbgl_layoutAddConfirmationButton(nbgl_layout_t *layout, + bool active, + const char *text, + int token, + tune_index_e tuneId); +int nbgl_layoutUpdateConfirmationButton(nbgl_layout_t *layout, + uint8_t index, + bool active, + const char *text); +#endif // NBGL_KEYBOARD #ifdef NBGL_KEYPAD /* layout objects for page with keypad */ int nbgl_layoutAddKeypad(nbgl_layout_t *layout, keyboardCallback_t callback, bool shuffled); -int nbgl_layoutUpdateKeypad(nbgl_layout_t *layout, uint8_t index, bool enableValidate, bool enableBackspace, bool enableDigits); +int nbgl_layoutUpdateKeypad(nbgl_layout_t *layout, + uint8_t index, + bool enableValidate, + bool enableBackspace, + bool enableDigits); int nbgl_layoutAddHiddenDigits(nbgl_layout_t *layout, uint8_t nbDigits); int nbgl_layoutUpdateHiddenDigits(nbgl_layout_t *layout, uint8_t index, uint8_t nbActive); -#endif // NBGL_KEYPAD +#endif // NBGL_KEYPAD /* generic functions */ int nbgl_layoutDraw(nbgl_layout_t *layout); @@ -324,7 +401,6 @@ int nbgl_layoutRelease(nbgl_layout_t *layout); * MACROS **********************/ - #ifdef __cplusplus } /* extern "C" */ #endif diff --git a/lib_nbgl/include/nbgl_obj.h b/lib_nbgl/include/nbgl_obj.h index 2480a1fb1..150206204 100644 --- a/lib_nbgl/include/nbgl_obj.h +++ b/lib_nbgl/include/nbgl_obj.h @@ -19,21 +19,21 @@ extern "C" { * INCLUDES *********************/ - /********************* * DEFINES *********************/ // Keypad special key values #define BACKSPACE_KEY 8 -#define VALIDATE_KEY '\r' +#define VALIDATE_KEY '\r' // for Keyboard -#define KEYBOARD_KEY_HEIGHT 60 +#define KEYBOARD_KEY_HEIGHT 60 // for Keypad -#define KEYPAD_KEY_HEIGHT 104 +#define KEYPAD_KEY_HEIGHT 104 -///< special code used by given callback of @ref nbgl_navigationPopulate to inform when Exit key is pressed +///< special code used by given callback of @ref nbgl_navigationPopulate to inform when Exit key is +///< pressed #define EXIT_PAGE 0xFF // external margin in pixels @@ -43,7 +43,7 @@ extern "C" { #define BACK_BUTTON_HEADER_HEIGHT 88 // common dimensions for buttons -#define BUTTON_RADIUS RADIUS_40_PIXELS +#define BUTTON_RADIUS RADIUS_40_PIXELS #define BUTTON_DIAMETER 80 /********************** @@ -54,30 +54,30 @@ extern "C" { * @brief All types of graphical objects. * */ -typedef enum { - SCREEN, ///< Main screen - CONTAINER, ///< Empty container - IMAGE, ///< Bitmap (x and width must be multiple of 4) - LINE, ///< Vertical or Horizontal line - TEXT_AREA, ///< Area to contain text line(s) - BUTTON, ///< Rounded rectangle button with icon and/or text - SWITCH, ///< Switch to turn on/off something - PAGE_INDICATOR, ///< horizontal bar to indicate position within pages - PROGRESS_BAR, ///< horizontal bar to indicate progression of something (between 0% and 100%) - RADIO_BUTTON, ///< Indicator to inform whether something is on or off - QR_CODE, ///< QR Code - KEYBOARD, ///< Keyboard - KEYPAD, ///< Keypad - SPINNER, ///< Spinner - IMAGE_FILE ///< Image file (with Ledger compression) +typedef enum { + SCREEN, ///< Main screen + CONTAINER, ///< Empty container + IMAGE, ///< Bitmap (x and width must be multiple of 4) + LINE, ///< Vertical or Horizontal line + TEXT_AREA, ///< Area to contain text line(s) + BUTTON, ///< Rounded rectangle button with icon and/or text + SWITCH, ///< Switch to turn on/off something + PAGE_INDICATOR, ///< horizontal bar to indicate position within pages + PROGRESS_BAR, ///< horizontal bar to indicate progression of something (between 0% and 100%) + RADIO_BUTTON, ///< Indicator to inform whether something is on or off + QR_CODE, ///< QR Code + KEYBOARD, ///< Keyboard + KEYPAD, ///< Keypad + SPINNER, ///< Spinner + IMAGE_FILE ///< Image file (with Ledger compression) } nbgl_obj_type_t; /** * @brief All types of alignments. * */ -typedef enum { - NO_ALIGNMENT, ///< used when parent container layout is used +typedef enum { + NO_ALIGNMENT, ///< used when parent container layout is used TOP_LEFT, TOP_MIDDLE, TOP_RIGHT, @@ -87,16 +87,16 @@ typedef enum { BOTTOM_LEFT, BOTTOM_MIDDLE, BOTTOM_RIGHT, - LEFT_TOP, ///< on outside left - LEFT_BOTTOM, ///< on outside left - RIGHT_TOP, ///< on outside right - RIGHT_BOTTOM, ///< on outside right + LEFT_TOP, ///< on outside left + LEFT_BOTTOM, ///< on outside left + RIGHT_TOP, ///< on outside right + RIGHT_BOTTOM, ///< on outside right } nbgl_aligment_t; /** * @brief to represent a boolean state. */ -typedef enum { +typedef enum { OFF_STATE, ON_STATE } nbgl_state_t; @@ -105,18 +105,18 @@ typedef enum { * @brief Directions for layout or lines * */ -typedef enum { - VERTICAL, ///< from top to bottom - HORIZONTAL ///< from left to right +typedef enum { + VERTICAL, ///< from top to bottom + HORIZONTAL ///< from left to right } nbgl_direction_t; /** * @brief possible styles for text area border * */ -typedef enum { - NO_STYLE, ///< no border - LEDGER_BORDER ///< Ledger style border, only for @ref TEXT_AREA +typedef enum { + NO_STYLE, ///< no border + LEDGER_BORDER ///< Ledger style border, only for @ref TEXT_AREA } nbgl_style_t; /** @@ -124,9 +124,9 @@ typedef enum { * @note if text len <= 114 chars, V4 can be used, otherwise use V10 * */ -typedef enum { - QRCODE_V4=0, ///< QRCode V4, can encode text len up to 114 chars - QRCODE_V10 ///< QRCode V10, can encode text len up to 1500 chars +typedef enum { + QRCODE_V4 = 0, ///< QRCode V4, can encode text len up to 114 chars + QRCODE_V10 ///< QRCode V10, can encode text len up to 1500 chars } nbgl_qrcode_version_t; /** @@ -134,8 +134,8 @@ typedef enum { * */ typedef enum { - RELEASED, ///< the finger has been released from the screen - PRESSED, ///< the finger is currently pressing the screen + RELEASED, ///< the finger has been released from the screen + PRESSED, ///< the finger is currently pressing the screen } nbgl_touchState_t; /** @@ -143,13 +143,18 @@ typedef enum { * */ typedef enum { - TOUCHED, ///< corresponding to an object touched and released at least SHORT_TOUCH_DURATION ms later but less than LONG_TOUCH_DURATION ms - LONG_TOUCHED, ///< corresponding to an object touched and released at least LONG_TOUCH_DURATION ms later. - TOUCHING, ///< corresponding to an object that is currently touched - OUT_OF_TOUCH, ///< corresponding to an object that was touched but that has lost the focus (the finger has moved) - TOUCH_PRESSED, ///< corresponding to an object that was not touched and where the finger has been pressed. - TOUCH_RELEASED, ///< corresponding to an object that was touched and where the finger has been released. - VALUE_CHANGED ///< corresponding to a change of state of the object (indirect event) + TOUCHED, ///< corresponding to an object touched and released at least SHORT_TOUCH_DURATION ms + ///< later but less than LONG_TOUCH_DURATION ms + LONG_TOUCHED, ///< corresponding to an object touched and released at least LONG_TOUCH_DURATION + ///< ms later. + TOUCHING, ///< corresponding to an object that is currently touched + OUT_OF_TOUCH, ///< corresponding to an object that was touched but that has lost the focus (the + ///< finger has moved) + TOUCH_PRESSED, ///< corresponding to an object that was not touched and where the finger has + ///< been pressed. + TOUCH_RELEASED, ///< corresponding to an object that was touched and where the finger has been + ///< released. + VALUE_CHANGED ///< corresponding to a change of state of the object (indirect event) } nbgl_touchType_t; /** @@ -158,7 +163,7 @@ typedef enum { */ typedef enum { PLAIN_COLOR_PANEL = 0, - ROUNDED_BORDER_PANEL ///< with a thin border in borderColor, with rounded corners + ROUNDED_BORDER_PANEL ///< with a thin border in borderColor, with rounded corners } nbgl_panelStyle_t; /** @@ -166,9 +171,10 @@ typedef enum { * */ typedef struct { - nbgl_touchState_t state; ///< state of the touch event, e.g @ref PRESSED or @ref RELEASED - int16_t x; ///< horizontal position of the touch (or for a @ref RELEASED the last touched point) - int16_t y; ///< vertical position of the touch (or for a @ref RELEASED the last touched point) + nbgl_touchState_t state; ///< state of the touch event, e.g @ref PRESSED or @ref RELEASED + int16_t + x; ///< horizontal position of the touch (or for a @ref RELEASED the last touched point) + int16_t y; ///< vertical position of the touch (or for a @ref RELEASED the last touched point) } nbgl_touchStatePosition_t; /** @@ -176,7 +182,7 @@ typedef struct { * @param obj the concerned object * @param eventType type of touch event */ -typedef void (*nbgl_touchCallback_t)(void *obj, nbgl_touchType_t eventType) ; +typedef void (*nbgl_touchCallback_t)(void *obj, nbgl_touchType_t eventType); /** * @brief Common structure for all graphical objects @@ -184,16 +190,19 @@ typedef void (*nbgl_touchCallback_t)(void *obj, nbgl_touchType_t eventType) ; * @note this type must never be instantiated */ typedef struct PACKED__ nbgl_obj_s { - nbgl_area_t area; ///< absolute position, backGround color and size of the object. DO NOT MOVE THIS FIELD - nbgl_obj_type_t type; ///< type of the graphical object, must be explicitly set - int16_t rel_x0; ///< horizontal position of top-left corner relative to parent's top-left corner - int16_t rel_y0; ///< vertical position of top-left corner relative to parent's top-left corner, must be multiple of 4 - struct nbgl_obj_s *parent; ///< parent of this object - struct nbgl_obj_s *alignTo; ///< object to align to (parent by default) - nbgl_aligment_t alignment; ///< type of alignment - int16_t alignmentMarginX; ///< horizontal margin when aligning - int16_t alignmentMarginY; ///< vertical margin when aligning - uint8_t touchMask; ///< bit mask to tell engine which touch events are handled by this object + nbgl_area_t area; ///< absolute position, backGround color and size of the object. DO NOT MOVE + ///< THIS FIELD + nbgl_obj_type_t type; ///< type of the graphical object, must be explicitly set + int16_t + rel_x0; ///< horizontal position of top-left corner relative to parent's top-left corner + int16_t rel_y0; ///< vertical position of top-left corner relative to parent's top-left corner, + ///< must be multiple of 4 + struct nbgl_obj_s *parent; ///< parent of this object + struct nbgl_obj_s *alignTo; ///< object to align to (parent by default) + nbgl_aligment_t alignment; ///< type of alignment + int16_t alignmentMarginX; ///< horizontal margin when aligning + int16_t alignmentMarginY; ///< vertical margin when aligning + uint8_t touchMask; ///< bit mask to tell engine which touch events are handled by this object } nbgl_obj_t; /** @@ -203,11 +212,11 @@ typedef struct PACKED__ nbgl_obj_s { * */ typedef struct PACKED__ nbgl_container_s { - nbgl_obj_t obj; ///< common part - nbgl_direction_t layout; ///< layout of children inside this object - uint8_t nbChildren; - bool forceClean; ///< if set to true, a paint will be done with background color - struct nbgl_obj_s **children; ///< children of this object (nbChildren size) + nbgl_obj_t obj; ///< common part + nbgl_direction_t layout; ///< layout of children inside this object + uint8_t nbChildren; + bool forceClean; ///< if set to true, a paint will be done with background color + struct nbgl_obj_s **children; ///< children of this object (nbChildren size) } nbgl_container_t; /** @@ -215,30 +224,36 @@ typedef struct PACKED__ nbgl_container_s { * */ typedef struct PACKED__ nbgl_line_s { - nbgl_obj_t obj; ///< common part - nbgl_direction_t direction; ///< direction of the line, e.g @ref VERTICAL or @ref HORIZONTAL - color_t lineColor; ///< color of the line - uint8_t thickness; ///< thickness of the line in pixel, maybe different from height for horizontal line - uint8_t offset; ///< the object height being always 4, with a y0 multiple of 4, this offset is use to move the line within these 4 pixels + nbgl_obj_t obj; ///< common part + nbgl_direction_t direction; ///< direction of the line, e.g @ref VERTICAL or @ref HORIZONTAL + color_t lineColor; ///< color of the line + uint8_t thickness; ///< thickness of the line in pixel, maybe different from height for + ///< horizontal line + uint8_t offset; ///< the object height being always 4, with a y0 multiple of 4, this offset is + ///< use to move the line within these 4 pixels } nbgl_line_t; /** - * @brief prototype of function to be called when a @ref IMAGE object is drawned, and no buffer was provided + * @brief prototype of function to be called when a @ref IMAGE object is drawned, and no buffer was + * provided * @param token provided token in @ref IMAGE object * @return the icn details to be drawned in image object */ -typedef nbgl_icon_details_t* (*onImageDrawCallback_t)(uint8_t token); +typedef nbgl_icon_details_t *(*onImageDrawCallback_t)(uint8_t token); /** * @brief struct to represent an image (@ref IMAGE type) * */ typedef struct PACKED__ nbgl_image_s { - nbgl_obj_t obj; // common part - color_t foregroundColor; ///< color set to '1' bits, for 1PBB images. '0' are set to background color. - const nbgl_icon_details_t *buffer; ///< buffer containing bitmap, with exact same size as object (width*height*bpp/8 bytes) - onImageDrawCallback_t onDrawCallback; ///< function called if buffer is NULL, with above token as parameter. Can be NULL - uint8_t token; ///< token to use as param of onDrawCallback + nbgl_obj_t obj; // common part + color_t foregroundColor; ///< color set to '1' bits, for 1PBB images. '0' are set to background + ///< color. + const nbgl_icon_details_t *buffer; ///< buffer containing bitmap, with exact same size as + ///< object (width*height*bpp/8 bytes) + onImageDrawCallback_t onDrawCallback; ///< function called if buffer is NULL, with above token + ///< as parameter. Can be NULL + uint8_t token; ///< token to use as param of onDrawCallback } nbgl_image_t; /** @@ -247,8 +262,8 @@ typedef struct PACKED__ nbgl_image_s { * */ typedef struct PACKED__ nbgl_image_file_s { - nbgl_obj_t obj; // common part - const uint8_t *buffer; ///< buffer containing image file + nbgl_obj_t obj; // common part + const uint8_t *buffer; ///< buffer containing image file } nbgl_image_file_t; /** @@ -256,10 +271,12 @@ typedef struct PACKED__ nbgl_image_file_s { * */ typedef struct PACKED__ nbgl_qrcode_s { - nbgl_obj_t obj; // common part - color_t foregroundColor; ///< color set to '1' bits, for 1PBB images. '0' are set to background color. - nbgl_qrcode_version_t version; ///< requested version, if V10, size will be fixed to 228*228, if V4, size will be fixed to 132*132 - const char *text; ///< text single line (NULL terminated) + nbgl_obj_t obj; // common part + color_t foregroundColor; ///< color set to '1' bits, for 1PBB images. '0' are set to background + ///< color. + nbgl_qrcode_version_t version; ///< requested version, if V10, size will be fixed to 228*228, + ///< if V4, size will be fixed to 132*132 + const char *text; ///< text single line (NULL terminated) } nbgl_qrcode_t; /** @@ -269,10 +286,10 @@ typedef struct PACKED__ nbgl_qrcode_s { * */ typedef struct PACKED__ nbgl_radio_s { - nbgl_obj_t obj; // common part - color_t activeColor; ///< color set to to inner circle, when active. - color_t borderColor; ///< color set to border. - nbgl_state_t state; ///< state of the radio button. Active is when state == @ref ON_STATE + nbgl_obj_t obj; // common part + color_t activeColor; ///< color set to to inner circle, when active. + color_t borderColor; ///< color set to border. + nbgl_state_t state; ///< state of the radio button. Active is when state == @ref ON_STATE } nbgl_radio_t; /** @@ -280,10 +297,10 @@ typedef struct PACKED__ nbgl_radio_s { * */ typedef struct PACKED__ nbgl_switch_s { - nbgl_obj_t obj; // common part - color_t onColor; ///< color set to border and knob, when ON (knob on the right). - color_t offColor; ///< color set to border and knob, when OFF (knob on the left). - nbgl_state_t state; ///< state of the switch. + nbgl_obj_t obj; // common part + color_t onColor; ///< color set to border and knob, when ON (knob on the right). + color_t offColor; ///< color set to border and knob, when OFF (knob on the left). + nbgl_state_t state; ///< state of the switch. } nbgl_switch_t; /** @@ -291,10 +308,10 @@ typedef struct PACKED__ nbgl_switch_s { * @note if withBorder, the stroke of the border is fixed (3 pixels) */ typedef struct PACKED__ nbgl_progress_bar_s { - nbgl_obj_t obj; // common part - bool withBorder; ///< if set to true, a border in black surround the whole object - uint8_t state; ///< state of the progress, in % (from 0 to 100). - color_t foregroundColor; ///< color of the inner progress bar and border (if applicable) + nbgl_obj_t obj; // common part + bool withBorder; ///< if set to true, a border in black surround the whole object + uint8_t state; ///< state of the progress, in % (from 0 to 100). + color_t foregroundColor; ///< color of the inner progress bar and border (if applicable) } nbgl_progress_bar_t; /** @@ -305,17 +322,18 @@ typedef struct PACKED__ nbgl_progress_bar_s { * @note height is fixed */ typedef struct PACKED__ nbgl_navigation_bar_s { - nbgl_obj_t obj; ///< common part - uint8_t nbPages; ///< number of pages. - uint8_t activePage; ///< index of active page (from 0 to nbPages-1). + nbgl_obj_t obj; ///< common part + uint8_t nbPages; ///< number of pages. + uint8_t activePage; ///< index of active page (from 0 to nbPages-1). } nbgl_page_indicator_t; /** - * @brief prototype of function to be called when a @ref TEXT_AREA object is drawned, and no text was provided + * @brief prototype of function to be called when a @ref TEXT_AREA object is drawned, and no text + * was provided * @param token provided token in @ref TEXT_AREA object * @return an ASCII string (null terminated) to be drawned in text area */ -typedef char* (*onTextDrawCallback_t)(uint8_t token); +typedef char *(*onTextDrawCallback_t)(uint8_t token); /** * @brief struct to represent a button (@ref BUTTON type) @@ -324,20 +342,22 @@ typedef char* (*onTextDrawCallback_t)(uint8_t token); * */ typedef struct PACKED__ nbgl_button_s { - nbgl_obj_t obj; ///< common part - color_t innerColor; ///< color set inside of the button - color_t borderColor; ///< color set to button's border - color_t foregroundColor; ///< color set to '1' bits in icon, and text. '0' are set to innerColor color. - nbgl_radius_t radius; ///< radius of the corners, must be a multiple of 4. - nbgl_font_id_e fontId; ///< id of the font to use, if any - bool localized; ///< if set to true, means the following 'text' field is considered as a - const char *text; ///< single line UTF-8 text (NULL terminated) + nbgl_obj_t obj; ///< common part + color_t innerColor; ///< color set inside of the button + color_t borderColor; ///< color set to button's border + color_t foregroundColor; ///< color set to '1' bits in icon, and text. '0' are set to + ///< innerColor color. + nbgl_radius_t radius; ///< radius of the corners, must be a multiple of 4. + nbgl_font_id_e fontId; ///< id of the font to use, if any + bool localized; ///< if set to true, means the following 'text' field is considered as a + const char *text; ///< single line UTF-8 text (NULL terminated) #if defined(HAVE_LANGUAGE_PACK) - UX_LOC_STRINGS_INDEX textId; ///< id of the text single line UTF-8 text -#endif // HAVE_LANGUAGE_PACK - onTextDrawCallback_t onDrawCallback; ///< function called if not NULL, with above token as parameter to get the text of the button - uint8_t token; ///< token to use as param of onDrawCallback - const nbgl_icon_details_t *icon; ///< buffer containing icons bitmap. Set to NULL when no icon + UX_LOC_STRINGS_INDEX textId; ///< id of the text single line UTF-8 text +#endif // HAVE_LANGUAGE_PACK + onTextDrawCallback_t onDrawCallback; ///< function called if not NULL, with above token as + ///< parameter to get the text of the button + uint8_t token; ///< token to use as param of onDrawCallback + const nbgl_icon_details_t *icon; ///< buffer containing icons bitmap. Set to NULL when no icon } nbgl_button_t; /** @@ -345,30 +365,35 @@ typedef struct PACKED__ nbgl_button_s { * */ typedef struct PACKED__ nbgl_text_area_s { - nbgl_obj_t obj; ///< common part - color_t textColor; ///< color set to '1' bits in text. '0' are set to backgroundColor color. - nbgl_aligment_t textAlignment; ///< alignment of text within the area - nbgl_style_t style; ///< to define the style of border - nbgl_font_id_e fontId; ///< id of the font to use - bool localized; ///< if set to true, use textId instead of text - bool autoHideLongLine; ///< if set to true, replace beginning of line by ... to keep it single line - bool wrapping; ///< if set to true, break lines on ' ' when possible - uint8_t nbMaxLines; ///< if >0, replace end (3 last chars) of line (nbMaxLines-1) by "..." and stop display here - const char *text; ///< ASCII text to draw (NULL terminated). Can be NULL. + nbgl_obj_t obj; ///< common part + color_t textColor; ///< color set to '1' bits in text. '0' are set to backgroundColor color. + nbgl_aligment_t textAlignment; ///< alignment of text within the area + nbgl_style_t style; ///< to define the style of border + nbgl_font_id_e fontId; ///< id of the font to use + bool localized; ///< if set to true, use textId instead of text + bool autoHideLongLine; ///< if set to true, replace beginning of line by ... to keep it single + ///< line + bool wrapping; ///< if set to true, break lines on ' ' when possible + uint8_t nbMaxLines; ///< if >0, replace end (3 last chars) of line (nbMaxLines-1) by "..." and + ///< stop display here + const char *text; ///< ASCII text to draw (NULL terminated). Can be NULL. #if defined(HAVE_LANGUAGE_PACK) - UX_LOC_STRINGS_INDEX textId; ///< id of the UTF-8 text -#endif // HAVE_LANGUAGE_PACK - onTextDrawCallback_t onDrawCallback; ///< function called if not NULL to get the text of the text area - uint8_t token; ///< token to use as param of onDrawCallback + UX_LOC_STRINGS_INDEX textId; ///< id of the UTF-8 text +#endif // HAVE_LANGUAGE_PACK + onTextDrawCallback_t + onDrawCallback; ///< function called if not NULL to get the text of the text area + uint8_t token; ///< token to use as param of onDrawCallback } nbgl_text_area_t; /** - * @brief struct to represent a "spinner", represented by the Ledger corners, in gray, with one of the corners in black (@ref SPINNER type) + * @brief struct to represent a "spinner", represented by the Ledger corners, in gray, with one of + * the corners in black (@ref SPINNER type) * */ typedef struct PACKED__ nbgl_spinner_s { - nbgl_obj_t obj; ///< common part - uint8_t position; ///< position of the spinner (from 0 to 3). If set to 0xFF, the spinner is entirely black + nbgl_obj_t obj; ///< common part + uint8_t position; ///< position of the spinner (from 0 to 3). If set to 0xFF, the spinner is + ///< entirely black } nbgl_spinner_t; /** @@ -383,9 +408,9 @@ typedef void (*keyboardCallback_t)(char touchedKey); * */ typedef enum { - MODE_LETTERS=0, ///< letters mode - MODE_DIGITS, ///< digits and some special characters mode - MODE_SPECIAL ///< extended special characters mode + MODE_LETTERS = 0, ///< letters mode + MODE_DIGITS, ///< digits and some special characters mode + MODE_SPECIAL ///< extended special characters mode } keyboardMode_t; /** @@ -393,9 +418,9 @@ typedef enum { * */ typedef enum { - LOWER_CASE=0, ///< lower case mode - UPPER_CASE, ///< upper case mode for one character - LOCKED_UPPER_CASE ///< locked upper case mode + LOWER_CASE = 0, ///< lower case mode + UPPER_CASE, ///< upper case mode for one character + LOCKED_UPPER_CASE ///< locked upper case mode } keyboardCase_t; /** @@ -403,38 +428,39 @@ typedef enum { * */ typedef struct PACKED__ nbgl_keyboard_s { - nbgl_obj_t obj; ///< common part - color_t textColor; ///< color set to letters. - color_t borderColor; ///< color set to key borders - bool lettersOnly; ///< if true, only display letter keys and Backspace - bool needsRefresh; ///< if true, means that the keyboard has been redrawn and needs a refresh - keyboardCase_t casing; ///< keyboard casing mode (lower, upper once or upper locked) - keyboardMode_t mode; ///< keyboard mode to start with - uint32_t keyMask; ///< mask used to disable some keys in letters only mod. The 26 LSB bits of mask are used, for the 26 letters of a QWERTY keyboard. Bit[0] for Q, Bit[1] for W and so on - keyboardCallback_t callback; ///< function called when an active key is pressed + nbgl_obj_t obj; ///< common part + color_t textColor; ///< color set to letters. + color_t borderColor; ///< color set to key borders + bool lettersOnly; ///< if true, only display letter keys and Backspace + bool needsRefresh; ///< if true, means that the keyboard has been redrawn and needs a refresh + keyboardCase_t casing; ///< keyboard casing mode (lower, upper once or upper locked) + keyboardMode_t mode; ///< keyboard mode to start with + uint32_t keyMask; ///< mask used to disable some keys in letters only mod. The 26 LSB bits of + ///< mask are used, for the 26 letters of a QWERTY keyboard. Bit[0] for Q, + ///< Bit[1] for W and so on + keyboardCallback_t callback; ///< function called when an active key is pressed } nbgl_keyboard_t; - /** * @brief struct to represent a keypad (@ref KEYPAD type) * */ typedef struct PACKED__ nbgl_keypad_s { - nbgl_obj_t obj; ///< common part - color_t textColor; ///< color set to digits. - color_t borderColor; ///< color set to key borders - bool enableBackspace; ///< if true, Backspace key is enabled - bool enableValidate; ///< if true, Validate key is enabled - bool enableDigits; ///< if true, Digit keys are enabled - bool shuffled; ///< if true, Digit keys are shuffled - uint8_t digitIndexes[5]; ///< array of digits indexes, 4 bits per digit - keyboardCallback_t callback; ///< function called when an active key is pressed + nbgl_obj_t obj; ///< common part + color_t textColor; ///< color set to digits. + color_t borderColor; ///< color set to key borders + bool enableBackspace; ///< if true, Backspace key is enabled + bool enableValidate; ///< if true, Validate key is enabled + bool enableDigits; ///< if true, Digit keys are enabled + bool shuffled; ///< if true, Digit keys are shuffled + uint8_t digitIndexes[5]; ///< array of digits indexes, 4 bits per digit + keyboardCallback_t callback; ///< function called when an active key is pressed } nbgl_keypad_t; /********************** * GLOBAL PROTOTYPES **********************/ -void nbgl_redrawObject(nbgl_obj_t* obj, nbgl_obj_t *prevObj, bool computePosition); +void nbgl_redrawObject(nbgl_obj_t *obj, nbgl_obj_t *prevObj, bool computePosition); void nbgl_refresh(void); void nbgl_refreshSpecial(nbgl_refresh_mode_t mode); @@ -445,18 +471,29 @@ void nbgl_refreshReset(void); void nbgl_objInit(void); void nbgl_objAllowDrawing(bool enable); -void nbgl_objPoolRelease(uint8_t layer); -nbgl_obj_t* nbgl_objPoolGet(nbgl_obj_type_t type, uint8_t layer); -nbgl_obj_t* nbgl_objPoolGetPrevious(nbgl_obj_t* obj, uint8_t layer); -int nbgl_objPoolGetArray(nbgl_obj_type_t type, uint8_t nbObjs, uint8_t layer, nbgl_obj_t** objArray); -uint8_t nbgl_objPoolGetNbUsed(uint8_t layer); -void nbgl_containerPoolRelease(uint8_t layer); -nbgl_obj_t** nbgl_containerPoolGet(uint8_t nbObjs, uint8_t layer); -uint8_t nbgl_containerPoolGetNbUsed(uint8_t layer); - -nbgl_container_t *nbgl_navigationPopulate(uint8_t nbPages, uint8_t activePage, bool withExitKey, uint8_t layer); -bool nbgl_navigationCallback(nbgl_obj_t *obj, nbgl_touchType_t eventType, uint8_t nbPages, uint8_t *activePage); -nbgl_container_t *nbgl_bottomButtonPopulate(const nbgl_icon_details_t *icon, bool separationLine, uint8_t layer); +void nbgl_objPoolRelease(uint8_t layer); +nbgl_obj_t *nbgl_objPoolGet(nbgl_obj_type_t type, uint8_t layer); +nbgl_obj_t *nbgl_objPoolGetPrevious(nbgl_obj_t *obj, uint8_t layer); +int nbgl_objPoolGetArray(nbgl_obj_type_t type, + uint8_t nbObjs, + uint8_t layer, + nbgl_obj_t **objArray); +uint8_t nbgl_objPoolGetNbUsed(uint8_t layer); +void nbgl_containerPoolRelease(uint8_t layer); +nbgl_obj_t **nbgl_containerPoolGet(uint8_t nbObjs, uint8_t layer); +uint8_t nbgl_containerPoolGetNbUsed(uint8_t layer); + +nbgl_container_t *nbgl_navigationPopulate(uint8_t nbPages, + uint8_t activePage, + bool withExitKey, + uint8_t layer); +bool nbgl_navigationCallback(nbgl_obj_t *obj, + nbgl_touchType_t eventType, + uint8_t nbPages, + uint8_t *activePage); +nbgl_container_t *nbgl_bottomButtonPopulate(const nbgl_icon_details_t *icon, + bool separationLine, + uint8_t layer); // for internal use void nbgl_objDrawKeyboard(nbgl_keyboard_t *kbd); diff --git a/lib_nbgl/include/nbgl_page.h b/lib_nbgl/include/nbgl_page.h index 6ac2f590c..b14a8bbe8 100644 --- a/lib_nbgl/include/nbgl_page.h +++ b/lib_nbgl/include/nbgl_page.h @@ -32,11 +32,11 @@ extern "C" { * */ typedef enum { - NO_BUTTON_STYLE=0, ///< no button. - SETTINGS_ICON, ///< settings (wheel) icon in the button. - QUIT_ICON, ///< quit (X) icon in the button. - INFO_ICON, ///< info (i) icon in the button. - QUIT_APP_TEXT ///< A full width button with "Quit app" text (only for bottom button) + NO_BUTTON_STYLE = 0, ///< no button. + SETTINGS_ICON, ///< settings (wheel) icon in the button. + QUIT_ICON, ///< quit (X) icon in the button. + INFO_ICON, ///< info (i) icon in the button. + QUIT_APP_TEXT ///< A full width button with "Quit app" text (only for bottom button) } nbgl_pageButtonStyle_t; /** @@ -44,113 +44,127 @@ typedef enum { * */ typedef enum { - CENTERED_INFO=0, ///< a centered info - INFO_LONG_PRESS, ///< a centered info and a long press button - INFO_BUTTON, ///< a centered info and a simple black button - TAG_VALUE_LIST, ///< list of tag/value pairs - TAG_VALUE_DETAILS, ///< a tag/value pair and a small button to get details. - TAG_VALUE_CONFIRM, ///< tag/value pairs and a black button/footer to confirm/cancel. - SWITCHES_LIST, ///< list of switches with descriptions - INFOS_LIST, ///< list of infos with titles - CHOICES_LIST, ///< list of choices through radio buttons - BARS_LIST ///< list of touchable bars (with > on the right to go to sub-pages) + CENTERED_INFO = 0, ///< a centered info + INFO_LONG_PRESS, ///< a centered info and a long press button + INFO_BUTTON, ///< a centered info and a simple black button + TAG_VALUE_LIST, ///< list of tag/value pairs + TAG_VALUE_DETAILS, ///< a tag/value pair and a small button to get details. + TAG_VALUE_CONFIRM, ///< tag/value pairs and a black button/footer to confirm/cancel. + SWITCHES_LIST, ///< list of switches with descriptions + INFOS_LIST, ///< list of infos with titles + CHOICES_LIST, ///< list of choices through radio buttons + BARS_LIST ///< list of touchable bars (with > on the right to go to sub-pages) } nbgl_pageContentType_t; /** * @brief This structure contains a [item,value] pair and info about "details" button */ typedef struct nbgl_pageTagValueDetails_s { - nbgl_layoutTagValueList_t tagValueList; ///< list of tag/value pairs - const nbgl_icon_details_t *detailsButtonIcon; ///< icon to use in details button - const char *detailsButtonText; ///< this text is used for "details" button - uint8_t detailsButtonToken; ///< the token used as argument of the actionCallback when the "details" button is touched - tune_index_e tuneId; ///< if not @ref NBGL_NO_TUNE, a tune will be played when details button is touched + nbgl_layoutTagValueList_t tagValueList; ///< list of tag/value pairs + const nbgl_icon_details_t *detailsButtonIcon; ///< icon to use in details button + const char *detailsButtonText; ///< this text is used for "details" button + uint8_t detailsButtonToken; ///< the token used as argument of the actionCallback when the + ///< "details" button is touched + tune_index_e + tuneId; ///< if not @ref NBGL_NO_TUNE, a tune will be played when details button is touched } nbgl_pageTagValueDetails_t; /** - * @brief This structure contains [item,value] pair(s) and info about a potential "details" button, but also a black button + footer to confirm/cancel + * @brief This structure contains [item,value] pair(s) and info about a potential "details" button, + * but also a black button + footer to confirm/cancel */ typedef struct nbgl_pageTagValueConfirm_s { - nbgl_layoutTagValueList_t tagValueList; ///< list of tag/value pairs - const nbgl_icon_details_t *detailsButtonIcon; ///< icon to use in details button - const char *detailsButtonText; ///< this text is used for "details" button (if NULL, no button) - uint8_t detailsButtonToken; ///< the token used as argument of the actionCallback when the "details" button is touched - tune_index_e tuneId; ///< if not @ref NBGL_NO_TUNE, a tune will be played when details button is touched - const char *confirmationText; ///< text of the confirmation button, if NULL "It matches" is used - const char *cancelText; ///< the text used for cancel action, if NULL "It doesn't matches" is used - uint8_t confirmationToken; ///< the token used as argument of the onActionCallback - uint8_t cancelToken; ///< the token used as argument of the onActionCallback when the cancel button is pressed + nbgl_layoutTagValueList_t tagValueList; ///< list of tag/value pairs + const nbgl_icon_details_t *detailsButtonIcon; ///< icon to use in details button + const char *detailsButtonText; ///< this text is used for "details" button (if NULL, no button) + uint8_t detailsButtonToken; ///< the token used as argument of the actionCallback when the + ///< "details" button is touched + tune_index_e + tuneId; ///< if not @ref NBGL_NO_TUNE, a tune will be played when details button is touched + const char + *confirmationText; ///< text of the confirmation button, if NULL "It matches" is used + const char + *cancelText; ///< the text used for cancel action, if NULL "It doesn't matches" is used + uint8_t confirmationToken; ///< the token used as argument of the onActionCallback + uint8_t cancelToken; ///< the token used as argument of the onActionCallback when the cancel + ///< button is pressed } nbgl_pageTagValueConfirm_t; /** * @brief This structure contains data to build a centered info + long press button page content */ typedef struct nbgl_pageInfoLongPress_s { - const char *text; ///< centered text in large case - const nbgl_icon_details_t *icon; ///< a buffer containing the 1BPP icon - const char *longPressText; ///< text of the long press button - uint8_t longPressToken; ///< the token used as argument of the onActionCallback when button is long pressed - tune_index_e tuneId; ///< if not @ref NBGL_NO_TUNE, a tune will be played when button is touched + const char *text; ///< centered text in large case + const nbgl_icon_details_t *icon; ///< a buffer containing the 1BPP icon + const char *longPressText; ///< text of the long press button + uint8_t longPressToken; ///< the token used as argument of the onActionCallback when button is + ///< long pressed + tune_index_e + tuneId; ///< if not @ref NBGL_NO_TUNE, a tune will be played when button is touched } nbgl_pageInfoLongPress_t; /** * @brief This structure contains data to build a centered info + simple black button page content */ typedef struct nbgl_pageInfoButton_s { - const char *text; ///< centered text in large case - const nbgl_icon_details_t *icon; ///< a buffer containing the 1BPP icon - const char *buttonText; ///< text of the long press button - uint8_t buttonToken; ///< the token used as argument of the onActionCallback when button is long pressed - tune_index_e tuneId; ///< if not @ref NBGL_NO_TUNE, a tune will be played when button is touched + const char *text; ///< centered text in large case + const nbgl_icon_details_t *icon; ///< a buffer containing the 1BPP icon + const char *buttonText; ///< text of the long press button + uint8_t buttonToken; ///< the token used as argument of the onActionCallback when button is + ///< long pressed + tune_index_e + tuneId; ///< if not @ref NBGL_NO_TUNE, a tune will be played when button is touched } nbgl_pageInfoButton_t; /** * @brief This structure contains data to build a @ref SWITCHES_LIST page content */ typedef struct nbgl_pageSwitchesList_s { - const nbgl_layoutSwitch_t *switches; ///< array of switches (nbSwitches items) - uint8_t nbSwitches; ///< number of elements in switches and tokens array + const nbgl_layoutSwitch_t *switches; ///< array of switches (nbSwitches items) + uint8_t nbSwitches; ///< number of elements in switches and tokens array } nbgl_pageSwitchesList_t; /** * @brief This structure contains data to build a @ref INFOS_LIST page content */ typedef struct nbgl_pageInfoList_s { - const char * const *infoTypes; ///< array of types of infos (in black/bold) - const char * const *infoContents; ///< array of contents of infos (in black) - uint8_t nbInfos; ///< number of elements in infoTypes and infoContents array + const char *const *infoTypes; ///< array of types of infos (in black/bold) + const char *const *infoContents; ///< array of contents of infos (in black) + uint8_t nbInfos; ///< number of elements in infoTypes and infoContents array } nbgl_pageInfoList_t; /** * @brief This structure contains data to build a @ref BARS_LIST page content */ typedef struct nbgl_pageBarsList_s { - const char * const *barTexts; ///< array of texts for each bar (nbBars items, in black/bold) - const uint8_t *tokens; ///< array of tokens, one for each bar (nbBars items) - uint8_t nbBars; ///< number of elements in barTexts and tokens array - tune_index_e tuneId; ///< if not @ref NBGL_NO_TUNE, a tune will be played when a bar is touched + const char *const *barTexts; ///< array of texts for each bar (nbBars items, in black/bold) + const uint8_t *tokens; ///< array of tokens, one for each bar (nbBars items) + uint8_t nbBars; ///< number of elements in barTexts and tokens array + tune_index_e tuneId; ///< if not @ref NBGL_NO_TUNE, a tune will be played when a bar is touched } nbgl_pageBarsList_t; /** - * @brief This structure contains data to build a page in multi-pages mode (@ref nbgl_pageDrawGenericContent) + * @brief This structure contains data to build a page in multi-pages mode (@ref + * nbgl_pageDrawGenericContent) */ typedef struct nbgl_pageContent_s { - const char *title; ///< text for the title of the page (if NULL, no title) - bool isTouchableTitle; ///< if set to true, the title is preceded by <- arrow to go back - uint8_t titleToken; ///< if isTouchableTitle set to true, this is the token used when touching title - tune_index_e tuneId; ///< if not @ref NBGL_NO_TUNE, a tune will be played when title is touched - nbgl_pageContentType_t type; ///< type of page content in the following union + const char *title; ///< text for the title of the page (if NULL, no title) + bool isTouchableTitle; ///< if set to true, the title is preceded by <- arrow to go back + uint8_t titleToken; ///< if isTouchableTitle set to true, this is the token used when touching + ///< title + tune_index_e tuneId; ///< if not @ref NBGL_NO_TUNE, a tune will be played when title is touched + nbgl_pageContentType_t type; ///< type of page content in the following union union { - nbgl_layoutTagValueList_t tagValueList; ///< @ref TAG_VALUE_LIST type - nbgl_layoutCenteredInfo_t centeredInfo; ///< @ref CENTERED_INFO type - nbgl_pageInfoLongPress_t infoLongPress; ///< @ref INFO_LONG_PRESS type - nbgl_pageInfoButton_t infoButton; ///< @ref INFO_BUTTON type - nbgl_pageTagValueDetails_t tagValueDetails; ///< @ref TAG_VALUE_DETAILS type - nbgl_pageTagValueConfirm_t tagValueConfirm; ///< @ref TAG_VALUE_CONFIRM type - nbgl_pageSwitchesList_t switchesList; ///< @ref SWITCHES_LIST type - nbgl_pageInfoList_t infosList; ///< @ref INFOS_LIST type - nbgl_layoutRadioChoice_t choicesList; ///< @ref CHOICES_LIST type - nbgl_pageBarsList_t barsList; ///< @ref BARS_LIST type + nbgl_layoutTagValueList_t tagValueList; ///< @ref TAG_VALUE_LIST type + nbgl_layoutCenteredInfo_t centeredInfo; ///< @ref CENTERED_INFO type + nbgl_pageInfoLongPress_t infoLongPress; ///< @ref INFO_LONG_PRESS type + nbgl_pageInfoButton_t infoButton; ///< @ref INFO_BUTTON type + nbgl_pageTagValueDetails_t tagValueDetails; ///< @ref TAG_VALUE_DETAILS type + nbgl_pageTagValueConfirm_t tagValueConfirm; ///< @ref TAG_VALUE_CONFIRM type + nbgl_pageSwitchesList_t switchesList; ///< @ref SWITCHES_LIST type + nbgl_pageInfoList_t infosList; ///< @ref INFOS_LIST type + nbgl_layoutRadioChoice_t choicesList; ///< @ref CHOICES_LIST type + nbgl_pageBarsList_t barsList; ///< @ref BARS_LIST type }; } nbgl_pageContent_t; @@ -158,16 +172,15 @@ typedef struct nbgl_pageContent_s { * @brief type shared externally * */ -typedef void* nbgl_page_t; - +typedef void *nbgl_page_t; /** * @brief The different types of navigation in a multi-screens page * */ typedef enum { - NAV_WITH_TAP, ///< move forward with "tap" and possibly backward with top left arrow - NAV_WITH_BUTTONS, ///< move forward and backward with buttons in bottom nav bar + NAV_WITH_TAP, ///< move forward with "tap" and possibly backward with top left arrow + NAV_WITH_BUTTONS, ///< move forward and backward with buttons in bottom nav bar } nbgl_pageNavigationType_t; /** @@ -175,13 +188,18 @@ typedef enum { * */ typedef struct nbgl_pageNavWithTap_s { - bool backButton; ///< if set to true, a back button (left arrow) is displayed in the top left corner (if page >=1) - uint8_t backToken; ///< the token used as argument of the actionCallback when the back button is touched - uint8_t nextPageToken; ///< the token used as argument of the actionCallback when the main panel is "tapped" - const char *nextPageText; ///< this text is used as indication for "Tap to continue", to navigate forward - const char * quitText; ///< the text displayed in footer, used to quit - const char *skipText; ///< if not NULL the text displayed in right part of footer, used for example to skip pages - uint8_t skipToken; ///< if skipText is NULL the token used when right part of footer is touched + bool backButton; ///< if set to true, a back button (left arrow) is displayed in the top left + ///< corner (if page >=1) + uint8_t backToken; ///< the token used as argument of the actionCallback when the back button + ///< is touched + uint8_t nextPageToken; ///< the token used as argument of the actionCallback when the main + ///< panel is "tapped" + const char *nextPageText; ///< this text is used as indication for "Tap to continue", to + ///< navigate forward + const char *quitText; ///< the text displayed in footer, used to quit + const char *skipText; ///< if not NULL the text displayed in right part of footer, used for + ///< example to skip pages + uint8_t skipToken; ///< if skipText is NULL the token used when right part of footer is touched } nbgl_pageNavWithTap_t; /** @@ -189,8 +207,9 @@ typedef struct nbgl_pageNavWithTap_s { * */ typedef struct nbgl_pageNavWithButtons_s { - bool quitButton; ///< if set to true, a quit button (X) is displayed in the nav bar - uint8_t navToken; ///< the token used as argument of the actionCallback when the nav buttons are pressed (index param gives the page) + bool quitButton; ///< if set to true, a quit button (X) is displayed in the nav bar + uint8_t navToken; ///< the token used as argument of the actionCallback when the nav buttons + ///< are pressed (index param gives the page) } nbgl_pageNavWithButtons_t; /** @@ -198,15 +217,18 @@ typedef struct nbgl_pageNavWithButtons_s { * */ typedef struct nbgl_pageMultiScreensDescription_s { - uint8_t activePage; ///< the index of the page to display at start-up - uint8_t nbPages; ///< the number of pages to display (if <2, no navigation bar) - uint8_t quitToken; ///< the token used as argument of the actionCallback when the footer is touched - nbgl_pageNavigationType_t navType; ///< type of navigation, it will tell which structure in the following union will be used - bool progressIndicator; ///< if set to true, display a progress indicator on top of the page - tune_index_e tuneId; ///< if not @ref NBGL_NO_TUNE, a tune will be played when next or back is pressed + uint8_t activePage; ///< the index of the page to display at start-up + uint8_t nbPages; ///< the number of pages to display (if <2, no navigation bar) + uint8_t + quitToken; ///< the token used as argument of the actionCallback when the footer is touched + nbgl_pageNavigationType_t navType; ///< type of navigation, it will tell which structure in the + ///< following union will be used + bool progressIndicator; ///< if set to true, display a progress indicator on top of the page + tune_index_e + tuneId; ///< if not @ref NBGL_NO_TUNE, a tune will be played when next or back is pressed union { - nbgl_pageNavWithTap_t navWithTap; ///< structure used when navigation with "tap" - nbgl_pageNavWithButtons_t navWithButtons; ///< structure used when navigation with buttons + nbgl_pageNavWithTap_t navWithTap; ///< structure used when navigation with "tap" + nbgl_pageNavWithButtons_t navWithButtons; ///< structure used when navigation with buttons }; } nbgl_pageNavigationInfo_t; @@ -214,69 +236,86 @@ typedef struct nbgl_pageMultiScreensDescription_s { * @brief Structure containing all specific information when creating a confirmation page. */ typedef struct nbgl_pageConfirmationDescription_s { - nbgl_layoutCenteredInfo_t centeredInfo; ///< description of the centered info to be used - const char *confirmationText; ///< text of the confirmation button - const char *cancelText; ///< the text used for cancel action, if NULL a simple X button is used - uint8_t confirmationToken; ///< the token used as argument of the onActionCallback - uint8_t cancelToken; ///< the token used as argument of the onActionCallback when the cancel button is pressed - tune_index_e tuneId; ///< if not @ref NBGL_NO_TUNE, a tune will be played when button is pressed - bool modal; ///< if true, page is open as a modal + nbgl_layoutCenteredInfo_t centeredInfo; ///< description of the centered info to be used + const char *confirmationText; ///< text of the confirmation button + const char *cancelText; ///< the text used for cancel action, if NULL a simple X button is used + uint8_t confirmationToken; ///< the token used as argument of the onActionCallback + uint8_t cancelToken; ///< the token used as argument of the onActionCallback when the cancel + ///< button is pressed + tune_index_e + tuneId; ///< if not @ref NBGL_NO_TUNE, a tune will be played when button is pressed + bool modal; ///< if true, page is open as a modal } nbgl_pageConfirmationDescription_t; /** * @brief Structure containing all specific information when creating a address confirmation page. - * This page contains the address in a tag/value format, and a white button to dipsplay the same address as a QRCode in - * a modal window. At the bottom 2 buttons allow to confirm or invalidate the address + * This page contains the address in a tag/value format, and a white button to dipsplay the same + * address as a QRCode in a modal window. At the bottom 2 buttons allow to confirm or invalidate the + * address */ typedef struct nbgl_pageAddressConfirmationDescription_s { - const char *address; ///< address to confirm - const char *qrCodeButtonText; ///< text to display in "QR code button", if NULL "Show as QR is used" - const char *confirmationText; ///< text of the confirmation button, if NULL "It matches" is used - const char *cancelText; ///< the text used for cancel action, if NULL "It doesn't matches" is used - uint8_t confirmationToken; ///< the token used as argument of the onActionCallback - uint8_t cancelToken; ///< the token used as argument of the onActionCallback when the cancel button is pressed - tune_index_e tuneId; ///< if not @ref NBGL_NO_TUNE, a tune will be played when button is pressed + const char *address; ///< address to confirm + const char + *qrCodeButtonText; ///< text to display in "QR code button", if NULL "Show as QR is used" + const char + *confirmationText; ///< text of the confirmation button, if NULL "It matches" is used + const char + *cancelText; ///< the text used for cancel action, if NULL "It doesn't matches" is used + uint8_t confirmationToken; ///< the token used as argument of the onActionCallback + uint8_t cancelToken; ///< the token used as argument of the onActionCallback when the cancel + ///< button is pressed + tune_index_e + tuneId; ///< if not @ref NBGL_NO_TUNE, a tune will be played when button is pressed } nbgl_pageAddressConfirmationDescription_t; /** * @brief Structure containing all specific information when creating an information page. */ typedef struct nbgl_pageInfoDescription_s { - nbgl_layoutCenteredInfo_t centeredInfo; ///< description of the centered info to be used - nbgl_pageButtonStyle_t topRightStyle; ///< style to apply to the Top-Right button - nbgl_pageButtonStyle_t bottomButtonStyle; ///< style to apply to the Bottom button - uint8_t topRightToken; ///< the token that will be used as argument of the onActionCallback - uint8_t bottomButtonsToken; ///< the token that will be used as argument of the onActionCallback if action/bottom button is touched - const char *footerText; ///< if not NULL, add a touchable footer - uint8_t footerToken; ///< the token that will be used as argument of the onActionCallback - const char *tapActionText; ///< if set to true, main area is "tapable", with this text as indication - uint8_t tapActionToken; ///< the token that will be used as argument of the onActionCallback - const char *actionButtonText; ///< if not NULL a black "action" button is set under the centered info - tune_index_e tuneId; ///< if not @ref NBGL_NO_TUNE, a tune will be played when button/footer is pressed + nbgl_layoutCenteredInfo_t centeredInfo; ///< description of the centered info to be used + nbgl_pageButtonStyle_t topRightStyle; ///< style to apply to the Top-Right button + nbgl_pageButtonStyle_t bottomButtonStyle; ///< style to apply to the Bottom button + uint8_t topRightToken; ///< the token that will be used as argument of the onActionCallback + uint8_t bottomButtonsToken; ///< the token that will be used as argument of the + ///< onActionCallback if action/bottom button is touched + const char *footerText; ///< if not NULL, add a touchable footer + uint8_t footerToken; ///< the token that will be used as argument of the onActionCallback + const char + *tapActionText; ///< if set to true, main area is "tapable", with this text as indication + uint8_t tapActionToken; ///< the token that will be used as argument of the onActionCallback + const char + *actionButtonText; ///< if not NULL a black "action" button is set under the centered info + tune_index_e + tuneId; ///< if not @ref NBGL_NO_TUNE, a tune will be played when button/footer is pressed } nbgl_pageInfoDescription_t; /********************** * GLOBAL PROTOTYPES **********************/ -nbgl_page_t* nbgl_pageDrawLedgerInfo(nbgl_layoutTouchCallback_t onActionCallback, const nbgl_screenTickerConfiguration_t *ticker, const char* text, int tapActionToken); -nbgl_page_t* nbgl_pageDrawSpinner(nbgl_layoutTouchCallback_t onActionCallback, const char* text); -nbgl_page_t* nbgl_pageDrawInfo(nbgl_layoutTouchCallback_t onActionCallback, const nbgl_screenTickerConfiguration_t *ticker, const nbgl_pageInfoDescription_t *info); -nbgl_page_t* nbgl_pageDrawConfirmation(nbgl_layoutTouchCallback_t onActionCallback, const nbgl_pageConfirmationDescription_t *info); -nbgl_page_t* nbgl_pageDrawGenericContentExt(nbgl_layoutTouchCallback_t onActionCallback, +nbgl_page_t *nbgl_pageDrawLedgerInfo(nbgl_layoutTouchCallback_t onActionCallback, + const nbgl_screenTickerConfiguration_t *ticker, + const char *text, + int tapActionToken); +nbgl_page_t *nbgl_pageDrawSpinner(nbgl_layoutTouchCallback_t onActionCallback, const char *text); +nbgl_page_t *nbgl_pageDrawInfo(nbgl_layoutTouchCallback_t onActionCallback, + const nbgl_screenTickerConfiguration_t *ticker, + const nbgl_pageInfoDescription_t *info); +nbgl_page_t *nbgl_pageDrawConfirmation(nbgl_layoutTouchCallback_t onActionCallback, + const nbgl_pageConfirmationDescription_t *info); +nbgl_page_t *nbgl_pageDrawGenericContentExt(nbgl_layoutTouchCallback_t onActionCallback, const nbgl_pageNavigationInfo_t *nav, - nbgl_pageContent_t* content, - bool modal); -nbgl_page_t* nbgl_pageDrawGenericContent(nbgl_layoutTouchCallback_t onActionCallback, - const nbgl_pageNavigationInfo_t *nav, - nbgl_pageContent_t* content); -int nbgl_pageRelease(nbgl_page_t*); + nbgl_pageContent_t *content, + bool modal); +nbgl_page_t *nbgl_pageDrawGenericContent(nbgl_layoutTouchCallback_t onActionCallback, + const nbgl_pageNavigationInfo_t *nav, + nbgl_pageContent_t *content); +int nbgl_pageRelease(nbgl_page_t *); /********************** * MACROS **********************/ - #ifdef __cplusplus } /* extern "C" */ #endif diff --git a/lib_nbgl/include/nbgl_screen.h b/lib_nbgl/include/nbgl_screen.h index 935b257c1..09d023623 100644 --- a/lib_nbgl/include/nbgl_screen.h +++ b/lib_nbgl/include/nbgl_screen.h @@ -36,9 +36,12 @@ typedef void (*nbgl_tickerCallback_t)(void); * */ typedef struct PACKED__ nbgl_screenTickerConfiguration_s { - nbgl_tickerCallback_t tickerCallback; ///< callback called when ticker timer is fired. Set to NULL for no ticker - uint32_t tickerValue; ///< timer initial value, in ms (should be multiple of 100 ms). Set to 0 for no ticker - uint32_t tickerIntervale; ///< for periodic timers, the intervale in ms to rearm the timer (should be multiple of 100 ms). Set to 0 for one-shot timers + nbgl_tickerCallback_t + tickerCallback; ///< callback called when ticker timer is fired. Set to NULL for no ticker + uint32_t tickerValue; ///< timer initial value, in ms (should be multiple of 100 ms). Set to 0 + ///< for no ticker + uint32_t tickerIntervale; ///< for periodic timers, the intervale in ms to rearm the timer + ///< (should be multiple of 100 ms). Set to 0 for one-shot timers } nbgl_screenTickerConfiguration_t; /** @@ -48,11 +51,14 @@ typedef struct PACKED__ nbgl_screenTickerConfiguration_s { * */ typedef struct PACKED__ nbgl_screen_s { - nbgl_container_t container; ///< common part - nbgl_screenTickerConfiguration_t ticker; ///< ticker configuration - nbgl_touchCallback_t touchCallback; ///< function to be called on events defined in touchMask field in each sub-object - struct nbgl_screen_s *next; ///< pointer to screen on top of this one (or NULL is this screen is top of stack) - struct nbgl_screen_s *previous; ///< pointer to screen on bottom of this one (or NULL is this screen is bottom of stack) + nbgl_container_t container; ///< common part + nbgl_screenTickerConfiguration_t ticker; ///< ticker configuration + nbgl_touchCallback_t touchCallback; ///< function to be called on events defined in touchMask + ///< field in each sub-object + struct nbgl_screen_s + *next; ///< pointer to screen on top of this one (or NULL is this screen is top of stack) + struct nbgl_screen_s *previous; ///< pointer to screen on bottom of this one (or NULL is this + ///< screen is bottom of stack) } nbgl_screen_t; /********************** @@ -63,34 +69,38 @@ unsigned int nbgl_screen_reinit(void); #ifdef HAVE_DISPLAY_FAST_MODE void nbgl_screen_update_temperature(uint8_t temp_degrees); -#endif // HAVE_DISPLAY_FAST_MODE +#endif // HAVE_DISPLAY_FAST_MODE #ifdef HAVE_CONFIGURABLE_DISPLAY_FAST_MODE void nbgl_screen_config_fast_mode(uint8_t fast_mode_setting); -#endif // HAVE_CONFIGURABLE_DISPLAY_FAST_MODE +#endif // HAVE_CONFIGURABLE_DISPLAY_FAST_MODE -void nbgl_screenRedraw(void); +void nbgl_screenRedraw(void); nbgl_obj_t *nbgl_screenGetTop(void); -uint8_t nbgl_screenGetCurrentStackSize(void); -bool nbgl_screenContainsObj(nbgl_obj_t *obj); +uint8_t nbgl_screenGetCurrentStackSize(void); +bool nbgl_screenContainsObj(nbgl_obj_t *obj); -int nbgl_screenSet(nbgl_obj_t*** elements, uint8_t nbElements, const nbgl_screenTickerConfiguration_t *ticker, nbgl_touchCallback_t touchCallback); +int nbgl_screenSet(nbgl_obj_t ***elements, + uint8_t nbElements, + const nbgl_screenTickerConfiguration_t *ticker, + nbgl_touchCallback_t touchCallback); int nbgl_screenUpdateNbElements(uint8_t screenIndex, uint8_t nbElements); int nbgl_screenUpdateBackgroundColor(uint8_t screenIndex, color_t color); int nbgl_screenUpdateTicker(uint8_t screenIndex, const nbgl_screenTickerConfiguration_t *ticker); nbgl_obj_t **nbgl_screenGetElements(uint8_t screenIndex); -int nbgl_screenRelease(void); -int nbgl_screenPush(nbgl_obj_t*** elements, uint8_t nbElements, const nbgl_screenTickerConfiguration_t *ticker, nbgl_touchCallback_t touchCallback); -int nbgl_screenPop(uint8_t screenIndex); -int nbgl_screenReset(void); -void nbgl_screenHandler(uint32_t intervaleMs); - +int nbgl_screenRelease(void); +int nbgl_screenPush(nbgl_obj_t ***elements, + uint8_t nbElements, + const nbgl_screenTickerConfiguration_t *ticker, + nbgl_touchCallback_t touchCallback); +int nbgl_screenPop(uint8_t screenIndex); +int nbgl_screenReset(void); +void nbgl_screenHandler(uint32_t intervaleMs); /********************** * MACROS **********************/ - #ifdef __cplusplus } /* extern "C" */ #endif diff --git a/lib_nbgl/include/nbgl_serialize.h b/lib_nbgl/include/nbgl_serialize.h index fbc6d99a6..537b9f883 100644 --- a/lib_nbgl/include/nbgl_serialize.h +++ b/lib_nbgl/include/nbgl_serialize.h @@ -2,16 +2,16 @@ #include "nbgl_obj.h" -#define NBGL_SERIALIZE_OK 0 +#define NBGL_SERIALIZE_OK 0 #define NBGL_SERIALIZE_ERROR 1 typedef enum nbgl_serialized_event_type_e { - NBGL_DRAW_OBJ = 0, - NBGL_REFRESH_AREA + NBGL_DRAW_OBJ = 0, + NBGL_REFRESH_AREA } nbgl_serialized_event_type_e; uint8_t nbgl_serializeNbglEvent(nbgl_serialized_event_type_e type, - nbgl_obj_t *obj, - uint8_t *out, - size_t *w_cnt, - size_t max_len); + nbgl_obj_t *obj, + uint8_t *out, + size_t *w_cnt, + size_t max_len); diff --git a/lib_nbgl/include/nbgl_side.h b/lib_nbgl/include/nbgl_side.h index 2a01e8979..c20071105 100644 --- a/lib_nbgl/include/nbgl_side.h +++ b/lib_nbgl/include/nbgl_side.h @@ -23,8 +23,7 @@ extern "C" { /** * Width of the side screen in pixels */ -#define SIDE_SCREEN_WIDTH 96 - +#define SIDE_SCREEN_WIDTH 96 /********************** * TYPEDEFS @@ -35,8 +34,11 @@ extern "C" { **********************/ void nbgl_sideDrawRect(nbgl_area_t *area); void nbgl_sideDrawHorizontalLine(nbgl_area_t *area, uint8_t mask, color_t lineColor); -void nbgl_sideDrawImage(nbgl_area_t *area, uint8_t* buffer, nbgl_transformation_t transformation, nbgl_color_map_t colorMap); -void nbgl_sideRefreshArea(nbgl_area_t * area, nbgl_post_refresh_t post_refresh); +void nbgl_sideDrawImage(nbgl_area_t *area, + uint8_t *buffer, + nbgl_transformation_t transformation, + nbgl_color_map_t colorMap); +void nbgl_sideRefreshArea(nbgl_area_t *area, nbgl_post_refresh_t post_refresh); /********************** * VARIABLES diff --git a/lib_nbgl/include/nbgl_touch.h b/lib_nbgl/include/nbgl_touch.h index 7a89ddbd5..32c37fc5d 100644 --- a/lib_nbgl/include/nbgl_touch.h +++ b/lib_nbgl/include/nbgl_touch.h @@ -23,7 +23,7 @@ extern "C" { // duration of a short touch on touch panel (in ms) #define SHORT_TOUCH_DURATION 0 // duration of a long touch on touch panel (in ms) -#define LONG_TOUCH_DURATION 1500 +#define LONG_TOUCH_DURATION 1500 /********************** * TYPEDEFS **********************/ @@ -31,15 +31,16 @@ extern "C" { /********************** * GLOBAL PROTOTYPES **********************/ -void nbgl_touchHandler(nbgl_touchStatePosition_t *touchEvent, uint32_t currentTimeMs); -bool nbgl_touchGetTouchedPosition(nbgl_obj_t *obj, nbgl_touchStatePosition_t **firstPos, nbgl_touchStatePosition_t **lastPos); +void nbgl_touchHandler(nbgl_touchStatePosition_t *touchEvent, uint32_t currentTimeMs); +bool nbgl_touchGetTouchedPosition(nbgl_obj_t *obj, + nbgl_touchStatePosition_t **firstPos, + nbgl_touchStatePosition_t **lastPos); uint32_t nbgl_touchGetTouchDuration(nbgl_obj_t *obj); /********************** * MACROS **********************/ - #ifdef __cplusplus } /* extern "C" */ #endif diff --git a/lib_nbgl/include/nbgl_types.h b/lib_nbgl/include/nbgl_types.h index 6f05b29c8..3d6f79e44 100644 --- a/lib_nbgl/include/nbgl_types.h +++ b/lib_nbgl/include/nbgl_types.h @@ -24,76 +24,75 @@ extern "C" { /** * Width of the front screen in pixels */ -#define SCREEN_WIDTH 400 +#define SCREEN_WIDTH 400 /** * Height of the front screen in pixels */ -#define SCREEN_HEIGHT 672 - +#define SCREEN_HEIGHT 672 /** * No transformation * */ -#define NO_TRANSFORMATION 0 +#define NO_TRANSFORMATION 0 /** * Horizontal mirroring when rendering bitmap * */ -#define HORIZONTAL_MIRROR 0x1 +#define HORIZONTAL_MIRROR 0x1 /** * Vertical mirroring when rendering bitmap * */ -#define VERTICAL_MIRROR 0x2 +#define VERTICAL_MIRROR 0x2 /** * Both directions mirroring when rendering bitmap * */ -#define BOTH_MIRRORS (HORIZONTAL_MIRROR|VERTICAL_MIRROR) +#define BOTH_MIRRORS (HORIZONTAL_MIRROR | VERTICAL_MIRROR) /** * Rotation 90 degrees clockwise when rendering bitmap * */ -#define ROTATE_90_CLOCKWISE 0x4 +#define ROTATE_90_CLOCKWISE 0x4 /** * Code to be used for color map when not used * */ -#define INVALID_COLOR_MAP 0x0 +#define INVALID_COLOR_MAP 0x0 /********************** * TYPEDEFS **********************/ #ifndef MIN -#define MIN(x,y) ((x)<(y)?(x):(y)) +#define MIN(x, y) ((x) < (y) ? (x) : (y)) #endif #ifndef MAX -#define MAX(x,y) ((x)>(y)?(x):(y)) +#define MAX(x, y) ((x) > (y) ? (x) : (y)) #endif #ifdef LINUX_SIMU #define PACKED__ -#else // LINUX_SIMU +#else // LINUX_SIMU #define PACKED__ __attribute__((packed)) -#endif// LINUX_SIMU +#endif // LINUX_SIMU #ifdef BICOLOR_MODE typedef enum { - BLACK=0, - DARK_GRAY=0, - LIGHT_GRAY=0, - WHITE=3 + BLACK = 0, + DARK_GRAY = 0, + LIGHT_GRAY = 0, + WHITE = 3 } color_t; #else typedef enum { - BLACK=0, + BLACK = 0, DARK_GRAY, LIGHT_GRAY, WHITE, @@ -107,10 +106,10 @@ typedef enum { * */ typedef enum { - NBGL_BPP_1=0, ///< 1 bit per pixel - NBGL_BPP_2, ///< 2 bits per pixel - NBGL_BPP_4, ///< 4 bits per pixel - NB_NBGL_BPP, ///< Number of NBGL_BPP enums + NBGL_BPP_1 = 0, ///< 1 bit per pixel + NBGL_BPP_2, ///< 2 bits per pixel + NBGL_BPP_4, ///< 4 bits per pixel + NB_NBGL_BPP, ///< Number of NBGL_BPP enums } nbgl_bpp_t; /** @@ -118,10 +117,10 @@ typedef enum { * */ typedef enum { - NBGL_NO_COMPRESSION = 0, ///< no compression, raw data - NBGL_GZLIB_COMPRESSION, ///< gzlib compression - NBGL_RLE_COMPRESSION, ///< RLE compression - NB_NBGL_COMPRESSION ///< Number of NBGL_COMPRESSION enums + NBGL_NO_COMPRESSION = 0, ///< no compression, raw data + NBGL_GZLIB_COMPRESSION, ///< gzlib compression + NBGL_RLE_COMPRESSION, ///< RLE compression + NB_NBGL_COMPRESSION ///< Number of NBGL_COMPRESSION enums } nbgl_compression_t; /** @@ -135,12 +134,12 @@ typedef enum { * */ typedef struct PACKED__ nbgl_area_s { - uint16_t x0; ///< horizontal position of the upper left point of the area - uint16_t y0; ///< vertical position of the upper left point of the area - uint16_t width; ///< width of the area, in pixels - uint16_t height; ///< height of the area, in pixels - color_t backgroundColor; ///< color (usually background) to be applied - nbgl_bpp_t bpp; ///< bits per pixel for this area + uint16_t x0; ///< horizontal position of the upper left point of the area + uint16_t y0; ///< vertical position of the upper left point of the area + uint16_t width; ///< width of the area, in pixels + uint16_t height; ///< height of the area, in pixels + color_t backgroundColor; ///< color (usually background) to be applied + nbgl_bpp_t bpp; ///< bits per pixel for this area } nbgl_area_t; /** @@ -148,15 +147,14 @@ typedef struct PACKED__ nbgl_area_s { * */ typedef enum { - FULL_COLOR_REFRESH, ///< to be used for normal refresh - FULL_COLOR_PARTIAL_REFRESH, ///< to be used for small partial refresh (radio buttons, switches) - FULL_COLOR_CLEAN_REFRESH, ///< to be used for lock screen display (cleaner but longer refresh) - BLACK_AND_WHITE_REFRESH, ///< to be used for pure B&W area, when contrast is important - BLACK_AND_WHITE_FAST_REFRESH, ///< to be used for pure B&W area, when contrast is not priority - NB_REFRESH_MODES + FULL_COLOR_REFRESH, ///< to be used for normal refresh + FULL_COLOR_PARTIAL_REFRESH, ///< to be used for small partial refresh (radio buttons, switches) + FULL_COLOR_CLEAN_REFRESH, ///< to be used for lock screen display (cleaner but longer refresh) + BLACK_AND_WHITE_REFRESH, ///< to be used for pure B&W area, when contrast is important + BLACK_AND_WHITE_FAST_REFRESH, ///< to be used for pure B&W area, when contrast is not priority + NB_REFRESH_MODES } nbgl_refresh_mode_t; - /** * @brief Available post-refresh power modes * @@ -165,24 +163,24 @@ typedef enum { * achieve a faster following refresh. */ typedef enum nbgl_post_refresh_t { - POST_REFRESH_FORCE_POWER_OFF, ///< Force screen power off after refresh - POST_REFRESH_FORCE_POWER_ON, ///< Force screen power on after refresh - POST_REFRESH_KEEP_POWER_STATE, ///< Keep screen power state after refresh + POST_REFRESH_FORCE_POWER_OFF, ///< Force screen power off after refresh + POST_REFRESH_FORCE_POWER_ON, ///< Force screen power on after refresh + POST_REFRESH_KEEP_POWER_STATE, ///< Keep screen power state after refresh } nbgl_post_refresh_t; /** * @brief possible radius for objects * */ -typedef enum { - RADIUS_4_PIXELS = 0, ///< 4 pixels - RADIUS_8_PIXELS, ///< 8 pixels - RADIUS_16_PIXELS, ///< 16 pixels - RADIUS_20_PIXELS, ///< 20 pixels - RADIUS_24_PIXELS, ///< 24 pixels - RADIUS_32_PIXELS, ///< 32 pixels - RADIUS_40_PIXELS, ///< 40 pixels - RADIUS_48_PIXELS, ///< 40 pixels +typedef enum { + RADIUS_4_PIXELS = 0, ///< 4 pixels + RADIUS_8_PIXELS, ///< 8 pixels + RADIUS_16_PIXELS, ///< 16 pixels + RADIUS_20_PIXELS, ///< 20 pixels + RADIUS_24_PIXELS, ///< 24 pixels + RADIUS_32_PIXELS, ///< 32 pixels + RADIUS_40_PIXELS, ///< 40 pixels + RADIUS_48_PIXELS, ///< 40 pixels RADIUS_0_PIXELS = 0xFF, ///< no radius (square angle) } nbgl_radius_t; @@ -204,14 +202,13 @@ typedef uint8_t nbgl_color_map_t; * */ typedef struct PACKED__ nbgl_icon_details_s { - uint16_t width; ///< width of the icon, in pixels - uint16_t height; ///< height of the icon, in pixels - nbgl_bpp_t bpp; ///< bits per pixel for this area - bool isFile; ///< if true, the bitmap buffer contains an image file + uint16_t width; ///< width of the icon, in pixels + uint16_t height; ///< height of the icon, in pixels + nbgl_bpp_t bpp; ///< bits per pixel for this area + bool isFile; ///< if true, the bitmap buffer contains an image file const uint8_t *bitmap; ///< buffer containing pixel values } nbgl_icon_details_t; - #ifdef __cplusplus } /* extern "C" */ #endif diff --git a/lib_nbgl/include/nbgl_use_case.h b/lib_nbgl/include/nbgl_use_case.h index 9fa9642b3..8f641db34 100644 --- a/lib_nbgl/include/nbgl_use_case.h +++ b/lib_nbgl/include/nbgl_use_case.h @@ -21,38 +21,38 @@ extern "C" { * DEFINES *********************/ /** - * @brief when using controls in page content (@ref nbgl_pageContent_t), this is the first token value - * usable for these controls + * @brief when using controls in page content (@ref nbgl_pageContent_t), this is the first token + * value usable for these controls */ #define FIRST_USER_TOKEN 20 /** - * @brief value of page parameter used with navigation callback when "skip" button is touched, to display the long press button to confirm - * review. + * @brief value of page parameter used with navigation callback when "skip" button is touched, to + * display the long press button to confirm review. */ #define LAST_PAGE_FOR_REVIEW 0xFF /** * @brief maximum number of lines for value field in details pages */ -#define NB_MAX_LINES_IN_DETAILS 12 +#define NB_MAX_LINES_IN_DETAILS 12 /** * @brief maximum number of lines for value field in review pages */ -#define NB_MAX_LINES_IN_REVIEW 9 +#define NB_MAX_LINES_IN_REVIEW 9 /** * @brief maximum number of simultaneously displayed pairs in review pages. * Can be useful when using nbgl_useCaseStaticReview() with the * callback mechanism to retrieve the item/value pairs. */ -#define NB_MAX_DISPLAYED_PAIRS_IN_REVIEW 4 +#define NB_MAX_DISPLAYED_PAIRS_IN_REVIEW 4 /** * @brief height available for tag/value pairs display */ -#define TAG_VALUE_AREA_HEIGHT 400 +#define TAG_VALUE_AREA_HEIGHT 400 /** * @brief Default strings used in the Home tagline @@ -68,7 +68,8 @@ extern "C" { /** * @brief Max supported length of appName used for the default Home tagline */ -#define MAX_APP_NAME_FOR_SDK_TAGLINE (APP_DESCRIPTION_MAX_LEN - 1 - (sizeof(TAGLINE_PART1) + sizeof(TAGLINE_PART2))) +#define MAX_APP_NAME_FOR_SDK_TAGLINE \ + (APP_DESCRIPTION_MAX_LEN - 1 - (sizeof(TAGLINE_PART1) + sizeof(TAGLINE_PART2))) /********************** * MACROS @@ -101,41 +102,83 @@ typedef void (*nbgl_choiceCallback_t)(bool confirm); **********************/ // utils -uint8_t nbgl_useCaseGetNbTagValuesInPage(uint8_t nbPairs, - const nbgl_layoutTagValueList_t *tagValueList, - uint8_t startIndex, - bool *tooLongToFit); +uint8_t nbgl_useCaseGetNbTagValuesInPage(uint8_t nbPairs, + const nbgl_layoutTagValueList_t *tagValueList, + uint8_t startIndex, + bool *tooLongToFit); uint8_t nbgl_useCaseGetNbPagesForTagValueList(const nbgl_layoutTagValueList_t *tagValueList); // use case drawing -void nbgl_useCaseHome(const char *appName, const nbgl_icon_details_t *appIcon, const char *tagline, bool withSettings, - nbgl_callback_t topRightCallback, nbgl_callback_t quitCallback); -void nbgl_useCaseHomeExt(const char *appName, const nbgl_icon_details_t *appIcon, const char *tagline, bool withSettings, - const char *actionButtonText, nbgl_callback_t actionCallback, - nbgl_callback_t topRightCallback, nbgl_callback_t quitCallback); -void nbgl_useCasePlugInHome(const char *plugInName, const char *appName, - const nbgl_icon_details_t *appIcon, const char *tagline, - const char *subTagline, bool withSettings, - nbgl_callback_t topRightCallback, nbgl_callback_t quitCallback); -void nbgl_useCaseSettings(const char *settingsTitle, uint8_t initPage, uint8_t nbPages, bool touchableTitle, - nbgl_callback_t quitCallback, nbgl_navCallback_t navCallback, +void nbgl_useCaseHome(const char *appName, + const nbgl_icon_details_t *appIcon, + const char *tagline, + bool withSettings, + nbgl_callback_t topRightCallback, + nbgl_callback_t quitCallback); +void nbgl_useCaseHomeExt(const char *appName, + const nbgl_icon_details_t *appIcon, + const char *tagline, + bool withSettings, + const char *actionButtonText, + nbgl_callback_t actionCallback, + nbgl_callback_t topRightCallback, + nbgl_callback_t quitCallback); +void nbgl_useCasePlugInHome(const char *plugInName, + const char *appName, + const nbgl_icon_details_t *appIcon, + const char *tagline, + const char *subTagline, + bool withSettings, + nbgl_callback_t topRightCallback, + nbgl_callback_t quitCallback); +void nbgl_useCaseSettings(const char *settingsTitle, + uint8_t initPage, + uint8_t nbPages, + bool touchableTitle, + nbgl_callback_t quitCallback, + nbgl_navCallback_t navCallback, nbgl_layoutTouchCallback_t controlsCallback); -void nbgl_useCaseChoice(const nbgl_icon_details_t *icon, const char *message, const char *subMessage, const char *confirmText, const char *rejectString, nbgl_choiceCallback_t callback); -void nbgl_useCaseConfirm(const char *message, const char *subMessage, const char *confirmText, const char *rejectText, nbgl_callback_t callback); +void nbgl_useCaseChoice(const nbgl_icon_details_t *icon, + const char *message, + const char *subMessage, + const char *confirmText, + const char *rejectString, + nbgl_choiceCallback_t callback); +void nbgl_useCaseConfirm(const char *message, + const char *subMessage, + const char *confirmText, + const char *rejectText, + nbgl_callback_t callback); void nbgl_useCaseStatus(const char *message, bool isSuccess, nbgl_callback_t quitCallback); -void nbgl_useCaseReviewStart(const nbgl_icon_details_t *icon, const char *reviewTitle, const char *reviewSubTitle, const char *rejectText, - nbgl_callback_t continueCallback, nbgl_callback_t rejectCallback); -void nbgl_useCaseRegularReview(uint8_t initPage, uint8_t nbPages, const char *rejectText, nbgl_layoutTouchCallback_t buttonCallback, - nbgl_navCallback_t navCallback, nbgl_choiceCallback_t choiceCallback); -void nbgl_useCaseForwardOnlyReview(const char *rejectText, nbgl_layoutTouchCallback_t buttonCallback, - nbgl_navCallback_t navCallback, nbgl_choiceCallback_t choiceCallback); -void nbgl_useCaseStaticReview(const nbgl_layoutTagValueList_t *tagValueList, const nbgl_pageInfoLongPress_t *infoLongPress, - const char *rejectText, nbgl_choiceCallback_t callback); -void nbgl_useCaseStaticReviewLight(const nbgl_layoutTagValueList_t *tagValueList, const nbgl_pageInfoLongPress_t *infoLongPress, - const char *rejectText, nbgl_choiceCallback_t callback); +void nbgl_useCaseReviewStart(const nbgl_icon_details_t *icon, + const char *reviewTitle, + const char *reviewSubTitle, + const char *rejectText, + nbgl_callback_t continueCallback, + nbgl_callback_t rejectCallback); +void nbgl_useCaseRegularReview(uint8_t initPage, + uint8_t nbPages, + const char *rejectText, + nbgl_layoutTouchCallback_t buttonCallback, + nbgl_navCallback_t navCallback, + nbgl_choiceCallback_t choiceCallback); +void nbgl_useCaseForwardOnlyReview(const char *rejectText, + nbgl_layoutTouchCallback_t buttonCallback, + nbgl_navCallback_t navCallback, + nbgl_choiceCallback_t choiceCallback); +void nbgl_useCaseStaticReview(const nbgl_layoutTagValueList_t *tagValueList, + const nbgl_pageInfoLongPress_t *infoLongPress, + const char *rejectText, + nbgl_choiceCallback_t callback); +void nbgl_useCaseStaticReviewLight(const nbgl_layoutTagValueList_t *tagValueList, + const nbgl_pageInfoLongPress_t *infoLongPress, + const char *rejectText, + nbgl_choiceCallback_t callback); void nbgl_useCaseViewDetails(const char *tag, const char *value, bool wrapping); void nbgl_useCaseAddressConfirmation(const char *address, nbgl_choiceCallback_t callback); -void nbgl_useCaseAddressConfirmationExt(const char *address, nbgl_choiceCallback_t callback, const nbgl_layoutTagValueList_t *tagValueList); +void nbgl_useCaseAddressConfirmationExt(const char *address, + nbgl_choiceCallback_t callback, + const nbgl_layoutTagValueList_t *tagValueList); void nbgl_useCaseSpinner(const char *text); #ifdef __cplusplus diff --git a/lib_nbgl/serialization/generate_data_test.c b/lib_nbgl/serialization/generate_data_test.c index d1ff62a80..c1fe32c56 100644 --- a/lib_nbgl/serialization/generate_data_test.c +++ b/lib_nbgl/serialization/generate_data_test.c @@ -5,182 +5,167 @@ #include "nbgl_serialize.h" #include "nbgl_obj.h" -void print_hex(const char *name, uint8_t *buffer, size_t len) { +void print_hex(const char *name, uint8_t *buffer, size_t len) +{ printf("%s,", name); - for(size_t i = 0; i < len; i++) { + for (size_t i = 0; i < len; i++) { printf("%02x", buffer[i]); } printf("\n"); } -void run_serialize_and_print(const char *name, nbgl_serialized_event_type_e event, nbgl_obj_t *obj) { +void run_serialize_and_print(const char *name, nbgl_serialized_event_type_e event, nbgl_obj_t *obj) +{ uint8_t buf[192]; - size_t len = 0; + size_t len = 0; nbgl_serializeNbglEvent(event, obj, buf, &len, sizeof(buf)); print_hex(name, buf, len); } -#define SERIALIZE_AND_PRINT(obj, event) run_serialize_and_print(__FUNCTION__, event, (nbgl_obj_t *) obj) +#define SERIALIZE_AND_PRINT(obj, event) \ + run_serialize_and_print(__FUNCTION__, event, (nbgl_obj_t *) obj) void test_draw_nbgl_container() { - nbgl_container_t container = { - .type = CONTAINER, + nbgl_container_t container = {.type = CONTAINER, - .backgroundColor = DARK_GRAY, - .bpp = NBGL_BPP_4, - .height = 450, - .width = 460, - .x0 = 56, - .y0 = 12, - - .layout = VERTICAL, - .nbChildren = 4, - .forceClean = true - }; + .backgroundColor = DARK_GRAY, + .bpp = NBGL_BPP_4, + .height = 450, + .width = 460, + .x0 = 56, + .y0 = 12, + + .layout = VERTICAL, + .nbChildren = 4, + .forceClean = true}; SERIALIZE_AND_PRINT(&container, NBGL_DRAW_OBJ); } void test_draw_nbgl_text_area() { - nbgl_text_area_t text = { - .type = TEXT_AREA, - - .backgroundColor = DARK_GRAY, - .bpp = NBGL_BPP_4, - .height = 400, - .width = 360, - .x0 = 12, - .y0 = 256, - - .textColor = BLACK, - .textAlignment = BOTTOM_RIGHT, - .style = LEDGER_BORDER, - .fontId = BAGL_FONT_INTER_MEDIUM_32px, - .localized = false, - .autoHideLongLine = true, - .text = "arthur" - }; + nbgl_text_area_t text = {.type = TEXT_AREA, + + .backgroundColor = DARK_GRAY, + .bpp = NBGL_BPP_4, + .height = 400, + .width = 360, + .x0 = 12, + .y0 = 256, + + .textColor = BLACK, + .textAlignment = BOTTOM_RIGHT, + .style = LEDGER_BORDER, + .fontId = BAGL_FONT_INTER_MEDIUM_32px, + .localized = false, + .autoHideLongLine = true, + .text = "arthur"}; SERIALIZE_AND_PRINT(&text, NBGL_DRAW_OBJ); } void test_draw_nbgl_line() { - nbgl_line_t line = { - .type = LINE, - .backgroundColor = WHITE, - .bpp = NBGL_BPP_1, - .height = 267, - .width = 36, - .x0 = 0, - .y0 = 42, - .direction = HORIZONTAL, - .lineColor = DARK_GRAY, - .thickness = 4, - .offset = 2 - }; + nbgl_line_t line = {.type = LINE, + .backgroundColor = WHITE, + .bpp = NBGL_BPP_1, + .height = 267, + .width = 36, + .x0 = 0, + .y0 = 42, + .direction = HORIZONTAL, + .lineColor = DARK_GRAY, + .thickness = 4, + .offset = 2}; SERIALIZE_AND_PRINT(&line, NBGL_DRAW_OBJ); } void test_draw_nbgl_qr_code() { - nbgl_qrcode_t qr_code = { - .type = QR_CODE, + nbgl_qrcode_t qr_code = {.type = QR_CODE, - .backgroundColor = DARK_GRAY, - .bpp = NBGL_BPP_2, - .height = 55, - .width = 66, - .x0 = 400, - .y0 = 300, - - .foregroundColor = DARK_GRAY, - .text = "fatstacks", - .version = QRCODE_V10 - }; + .backgroundColor = DARK_GRAY, + .bpp = NBGL_BPP_2, + .height = 55, + .width = 66, + .x0 = 400, + .y0 = 300, + + .foregroundColor = DARK_GRAY, + .text = "fatstacks", + .version = QRCODE_V10}; SERIALIZE_AND_PRINT(&qr_code, NBGL_DRAW_OBJ); } void test_draw_nbgl_radio() { - nbgl_radio_t radio = { - .type = RADIO_BUTTON, - - .backgroundColor = BLACK, - .bpp = NBGL_BPP_4, - .height = 100, - .width = 200, - .x0 = 123, - .y0 = 234, - - .activeColor = BLACK, - .borderColor = DARK_GRAY, - .state = ON_STATE - }; + nbgl_radio_t radio = {.type = RADIO_BUTTON, + + .backgroundColor = BLACK, + .bpp = NBGL_BPP_4, + .height = 100, + .width = 200, + .x0 = 123, + .y0 = 234, + + .activeColor = BLACK, + .borderColor = DARK_GRAY, + .state = ON_STATE}; SERIALIZE_AND_PRINT(&radio, NBGL_DRAW_OBJ); } void test_draw_nbgl_switch() { - nbgl_switch_t switch_obj = { - .type = SWITCH, + nbgl_switch_t switch_obj = {.type = SWITCH, - .backgroundColor = LIGHT_GRAY, - .bpp = NBGL_BPP_1, - .height = 333, - .width = 89, - .x0 = 1, - .y0 = 10000, - - .offColor = WHITE, - .onColor = BLACK, - .state = OFF_STATE - }; + .backgroundColor = LIGHT_GRAY, + .bpp = NBGL_BPP_1, + .height = 333, + .width = 89, + .x0 = 1, + .y0 = 10000, + + .offColor = WHITE, + .onColor = BLACK, + .state = OFF_STATE}; SERIALIZE_AND_PRINT(&switch_obj, NBGL_DRAW_OBJ); } - - void test_draw_nbgl_progress_bar() { - nbgl_progress_bar_t progress_bar = { - .type = PROGRESS_BAR, - - .backgroundColor = BLACK, - .bpp = NBGL_BPP_1, - .height = 10000, - .width = 11000, - .x0 = 12000, - .y0 = 13000, - - .withBorder = true, - .state = 91 - }; + nbgl_progress_bar_t progress_bar = {.type = PROGRESS_BAR, + + .backgroundColor = BLACK, + .bpp = NBGL_BPP_1, + .height = 10000, + .width = 11000, + .x0 = 12000, + .y0 = 13000, + + .withBorder = true, + .state = 91}; SERIALIZE_AND_PRINT(&progress_bar, NBGL_DRAW_OBJ); } void test_draw_nbgl_page_indicator() { - nbgl_page_indicator_t page_indicator = { - .type = PAGE_INDICATOR, - - .backgroundColor = BLACK, - .bpp = NBGL_BPP_2, - .height = 11, - .width = 22, - .x0 = 33, - .y0 = 44, - - .activePage = 2, - .nbPages = 10 - }; + nbgl_page_indicator_t page_indicator = {.type = PAGE_INDICATOR, + + .backgroundColor = BLACK, + .bpp = NBGL_BPP_2, + .height = 11, + .width = 22, + .x0 = 33, + .y0 = 44, + + .activePage = 2, + .nbPages = 10}; SERIALIZE_AND_PRINT(&page_indicator, NBGL_DRAW_OBJ); } @@ -191,19 +176,19 @@ void test_draw_nbgl_button() .type = BUTTON, .backgroundColor = DARK_GRAY, - .bpp = NBGL_BPP_1, - .height = 50, - .width = 255, - .x0 = 500, - .y0 = 1000, - - .innerColor = WHITE, - .borderColor = DARK_GRAY, + .bpp = NBGL_BPP_1, + .height = 50, + .width = 255, + .x0 = 500, + .y0 = 1000, + + .innerColor = WHITE, + .borderColor = DARK_GRAY, .foregroundColor = LIGHT_GRAY, - .radius = RADIUS_24_PIXELS, - .fontId = BAGL_FONT_HM_ALPHA_MONO_MEDIUM_32px, - .localized = true, - .text = "Test button", + .radius = RADIUS_24_PIXELS, + .fontId = BAGL_FONT_HM_ALPHA_MONO_MEDIUM_32px, + .localized = true, + .text = "Test button", }; SERIALIZE_AND_PRINT(&button, NBGL_DRAW_OBJ); @@ -211,18 +196,16 @@ void test_draw_nbgl_button() void test_draw_nbgl_image() { - nbgl_image_t image = { - .type = IMAGE, + nbgl_image_t image = {.type = IMAGE, - .backgroundColor = WHITE, - .bpp = NBGL_BPP_2, - .height = 101, - .width = 201, - .x0 = 124, - .y0 = 235, + .backgroundColor = WHITE, + .bpp = NBGL_BPP_2, + .height = 101, + .width = 201, + .x0 = 124, + .y0 = 235, - .foregroundColor = DARK_GRAY - }; + .foregroundColor = DARK_GRAY}; SERIALIZE_AND_PRINT(&image, NBGL_DRAW_OBJ); } @@ -233,18 +216,18 @@ void test_draw_nbgl_keyboard() .type = KEYBOARD, .backgroundColor = LIGHT_GRAY, - .bpp = NBGL_BPP_2, - .height = 210, - .width = 225, - .x0 = 332, - .y0 = 431, + .bpp = NBGL_BPP_2, + .height = 210, + .width = 225, + .x0 = 332, + .y0 = 431, - .textColor = WHITE, + .textColor = WHITE, .borderColor = BLACK, .lettersOnly = true, - .upperCase = false, - .mode = MODE_DIGITS, - .keyMask = 0x12345678, + .upperCase = false, + .mode = MODE_DIGITS, + .keyMask = 0x12345678, }; SERIALIZE_AND_PRINT(&keyboard, NBGL_DRAW_OBJ); @@ -252,39 +235,35 @@ void test_draw_nbgl_keyboard() void test_draw_nbgl_keypad() { - nbgl_keypad_t keypad = { - .type = KEYPAD, + nbgl_keypad_t keypad = {.type = KEYPAD, - .backgroundColor = WHITE, - .bpp = NBGL_BPP_4, - .height = 4, - .width = 4, - .x0 = 3, - .y0 = 4, + .backgroundColor = WHITE, + .bpp = NBGL_BPP_4, + .height = 4, + .width = 4, + .x0 = 3, + .y0 = 4, - .textColor = WHITE, - .borderColor = BLACK, - .enableBackspace = true, - .enableValidate = false - }; + .textColor = WHITE, + .borderColor = BLACK, + .enableBackspace = true, + .enableValidate = false}; SERIALIZE_AND_PRINT(&keypad, NBGL_DRAW_OBJ); } void test_draw_nbgl_spinner() { - nbgl_spinner_t spinner = { - .type = SPINNER, + nbgl_spinner_t spinner = {.type = SPINNER, - .backgroundColor = LIGHT_GRAY, - .bpp = NBGL_BPP_1, - .height = 14, - .width = 25, - .x0 = 12, - .y0 = 10, + .backgroundColor = LIGHT_GRAY, + .bpp = NBGL_BPP_1, + .height = 14, + .width = 25, + .x0 = 12, + .y0 = 10, - .position = 2 - }; + .position = 2}; SERIALIZE_AND_PRINT(&spinner, NBGL_DRAW_OBJ); } @@ -295,11 +274,11 @@ void test_draw_nbgl_image_file() .type = IMAGE_FILE, .backgroundColor = DARK_GRAY, - .bpp = NBGL_BPP_4, - .height = 24, - .width = 35, - .x0 = 22, - .y0 = 20, + .bpp = NBGL_BPP_4, + .height = 24, + .width = 35, + .x0 = 22, + .y0 = 20, }; SERIALIZE_AND_PRINT(&image_file, NBGL_DRAW_OBJ); @@ -309,11 +288,11 @@ void test_refresh_area() { nbgl_area_t area = { .backgroundColor = WHITE, - .bpp = NBGL_BPP_4, - .height = 4, - .width = 4, - .x0 = 3, - .y0 = 4, + .bpp = NBGL_BPP_4, + .height = 4, + .width = 4, + .x0 = 3, + .y0 = 4, }; SERIALIZE_AND_PRINT(&area, NBGL_REFRESH_AREA); diff --git a/lib_nbgl/src/nbgl_bottom_button.c b/lib_nbgl/src/nbgl_bottom_button.c index 97b7b1c6d..e798a592a 100644 --- a/lib_nbgl/src/nbgl_bottom_button.c +++ b/lib_nbgl/src/nbgl_bottom_button.c @@ -21,9 +21,9 @@ * TYPEDEFS **********************/ enum { - QUIT_BUTTON_INDEX = 0, - LINE_INDEX, - NB_MAX_CHILDREN + QUIT_BUTTON_INDEX = 0, + LINE_INDEX, + NB_MAX_CHILDREN }; /********************** @@ -38,56 +38,59 @@ enum { * VARIABLES **********************/ - /********************** * GLOBAL FUNCTIONS **********************/ /** - * @brief This function creates a bottom area with a centered button and a top line. Returns it as a container + * @brief This function creates a bottom area with a centered button and a top line. Returns it as a + * container * * @param icon icon to place in centered button * @param separationLine if set to true, adds a light gray separation line on top of the container * @param layer screen layer to use * @return the created container object */ -nbgl_container_t *nbgl_bottomButtonPopulate(const nbgl_icon_details_t *icon, bool separationLine, uint8_t layer) { - nbgl_button_t *button; - nbgl_container_t *container; +nbgl_container_t *nbgl_bottomButtonPopulate(const nbgl_icon_details_t *icon, + bool separationLine, + uint8_t layer) +{ + nbgl_button_t *button; + nbgl_container_t *container; - container = (nbgl_container_t *)nbgl_objPoolGet(CONTAINER, layer); - container->obj.area.width = SCREEN_WIDTH; - container->obj.area.height = BUTTON_DIAMETER+2*BORDER_MARGIN; - container->layout = HORIZONTAL ; - container->nbChildren = NB_MAX_CHILDREN; - container->children = (nbgl_obj_t**)nbgl_containerPoolGet(container->nbChildren, layer); - container->obj.alignment = NO_ALIGNMENT; + container = (nbgl_container_t *) nbgl_objPoolGet(CONTAINER, layer); + container->obj.area.width = SCREEN_WIDTH; + container->obj.area.height = BUTTON_DIAMETER + 2 * BORDER_MARGIN; + container->layout = HORIZONTAL; + container->nbChildren = NB_MAX_CHILDREN; + container->children = (nbgl_obj_t **) nbgl_containerPoolGet(container->nbChildren, layer); + container->obj.alignment = NO_ALIGNMENT; - button = (nbgl_button_t*)nbgl_objPoolGet(BUTTON,layer); - button->innerColor = WHITE; - button->borderColor = LIGHT_GRAY; - button->obj.area.width = BUTTON_DIAMETER; - button->obj.area.height = BUTTON_DIAMETER; - button->radius = BUTTON_RADIUS; - button->icon = icon; - button->obj.alignment = CENTER; - button->obj.touchMask = (1<children[QUIT_BUTTON_INDEX] = (nbgl_obj_t*)button; + button = (nbgl_button_t *) nbgl_objPoolGet(BUTTON, layer); + button->innerColor = WHITE; + button->borderColor = LIGHT_GRAY; + button->obj.area.width = BUTTON_DIAMETER; + button->obj.area.height = BUTTON_DIAMETER; + button->radius = BUTTON_RADIUS; + button->icon = icon; + button->obj.alignment = CENTER; + button->obj.touchMask = (1 << TOUCHED); + container->children[QUIT_BUTTON_INDEX] = (nbgl_obj_t *) button; - if (separationLine) { - nbgl_line_t *line; - // create horizontal line - line = (nbgl_line_t*)nbgl_objPoolGet(LINE,0); - line->lineColor = LIGHT_GRAY; - line->obj.area.width = SCREEN_WIDTH; - line->obj.area.height = 4; - line->direction = HORIZONTAL; - line->thickness = 1; - line->obj.alignmentMarginY = BORDER_MARGIN-4; - line->obj.alignTo = (nbgl_obj_t*)button; - line->obj.alignment = TOP_MIDDLE; - container->children[LINE_INDEX] = (nbgl_obj_t*)line; - } + if (separationLine) { + nbgl_line_t *line; + // create horizontal line + line = (nbgl_line_t *) nbgl_objPoolGet(LINE, 0); + line->lineColor = LIGHT_GRAY; + line->obj.area.width = SCREEN_WIDTH; + line->obj.area.height = 4; + line->direction = HORIZONTAL; + line->thickness = 1; + line->obj.alignmentMarginY = BORDER_MARGIN - 4; + line->obj.alignTo = (nbgl_obj_t *) button; + line->obj.alignment = TOP_MIDDLE; + container->children[LINE_INDEX] = (nbgl_obj_t *) line; + } - return container; + return container; } diff --git a/lib_nbgl/src/nbgl_draw.c b/lib_nbgl/src/nbgl_draw.c index 4b8891b43..b9832ca54 100644 --- a/lib_nbgl/src/nbgl_draw.c +++ b/lib_nbgl/src/nbgl_draw.c @@ -36,15 +36,15 @@ **********************/ #ifdef NBGL_QRCODE typedef struct { - uint8_t qrcode[qrcodegen_BUFFER_LEN_MAX]; - uint8_t tempBuffer[qrcodegen_BUFFER_LEN_MAX]; - uint8_t QrDrawBuffer[QR_PIXEL_WIDTH_HEIGHT * QR_PIXEL_WIDTH_HEIGHT * QR_MAX_PIX_SIZE / 8]; + uint8_t qrcode[qrcodegen_BUFFER_LEN_MAX]; + uint8_t tempBuffer[qrcodegen_BUFFER_LEN_MAX]; + uint8_t QrDrawBuffer[QR_PIXEL_WIDTH_HEIGHT * QR_PIXEL_WIDTH_HEIGHT * QR_MAX_PIX_SIZE / 8]; } QrCodeBuffer_t; #endif -#define qrcode ((QrCodeBuffer_t*)ramBuffer)->qrcode -#define tempBuffer ((QrCodeBuffer_t*)ramBuffer)->tempBuffer -#define QrDrawBuffer ((QrCodeBuffer_t*)ramBuffer)->QrDrawBuffer +#define qrcode ((QrCodeBuffer_t *) ramBuffer)->qrcode +#define tempBuffer ((QrCodeBuffer_t *) ramBuffer)->tempBuffer +#define QrDrawBuffer ((QrCodeBuffer_t *) ramBuffer)->QrDrawBuffer /********************** * STATIC PROTOTYPES @@ -53,49 +53,41 @@ typedef struct { /********************** * STATIC VARIABLES **********************/ -static const uint8_t quarter_disc_4px_1bpp[] = { - 0x13, 0xFF -}; -static const nbgl_icon_details_t C_quarter_disc_4px_1bpp= { 4, 4, NBGL_BPP_1, false, quarter_disc_4px_1bpp}; +static const uint8_t quarter_disc_4px_1bpp[] = {0x13, 0xFF}; +static const nbgl_icon_details_t C_quarter_disc_4px_1bpp + = {4, 4, NBGL_BPP_1, false, quarter_disc_4px_1bpp}; -static const uint8_t quarter_circle_4px_1bpp[] = { - 0x13, 0xFF -}; -static const nbgl_icon_details_t C_quarter_circle_4px_1bpp= { 4, 4, NBGL_BPP_1, false, quarter_circle_4px_1bpp}; +static const uint8_t quarter_circle_4px_1bpp[] = {0x13, 0xFF}; +static const nbgl_icon_details_t C_quarter_circle_4px_1bpp + = {4, 4, NBGL_BPP_1, false, quarter_circle_4px_1bpp}; // indexed by nbgl_radius_t (except RADIUS_0_PIXELS) -static const uint8_t radiusValues[] = { - 4, 8, 16, 20, 24, 32, 40, 48 -}; +static const uint8_t radiusValues[] = {4, 8, 16, 20, 24, 32, 40, 48}; // indexed by nbgl_radius_t (except RADIUS_0_PIXELS) -static const nbgl_icon_details_t* quarterDiscs[] = { - &C_quarter_disc_4px_1bpp, - &C_quarter_round_8px_1bpp, - &C_quarter_round_16px_1bpp, - &C_quarter_round_20px_1bpp, - &C_quarter_round_24px_1bpp, - &C_quarter_round_32px_1bpp, - &C_quarter_round_40px_1bpp, - &C_quarter_round_48px_1bpp -}; +static const nbgl_icon_details_t *quarterDiscs[] = {&C_quarter_disc_4px_1bpp, + &C_quarter_round_8px_1bpp, + &C_quarter_round_16px_1bpp, + &C_quarter_round_20px_1bpp, + &C_quarter_round_24px_1bpp, + &C_quarter_round_32px_1bpp, + &C_quarter_round_40px_1bpp, + &C_quarter_round_48px_1bpp}; // indexed by nbgl_radius_t (except RADIUS_0_PIXELS) -static const nbgl_icon_details_t* quarterCircles[] = { - &C_quarter_circle_4px_1bpp, - &C_quarter_circle_8px_1bpp, - &C_quarter_circle_16px_1bpp, - &C_quarter_circle_20px_1bpp, - &C_quarter_circle_24px_1bpp, - &C_quarter_circle_32px_1bpp, - &C_quarter_circle_40px_1bpp, - &C_quarter_circle_48px_1bpp -}; +static const nbgl_icon_details_t *quarterCircles[] = {&C_quarter_circle_4px_1bpp, + &C_quarter_circle_8px_1bpp, + &C_quarter_circle_16px_1bpp, + &C_quarter_circle_20px_1bpp, + &C_quarter_circle_24px_1bpp, + &C_quarter_circle_32px_1bpp, + &C_quarter_circle_40px_1bpp, + &C_quarter_circle_48px_1bpp}; #ifdef NBGL_QRCODE // ensure that the ramBuffer also used for image file decompression is big enough for QR code CCASSERT(qr_code_buffer, sizeof(QrCodeBuffer_t) <= GZLIB_UNCOMPRESSED_CHUNK); -#endif // NBGL_QRCODE +#endif // NBGL_QRCODE /********************** * VARIABLES @@ -105,45 +97,51 @@ CCASSERT(qr_code_buffer, sizeof(QrCodeBuffer_t) <= GZLIB_UNCOMPRESSED_CHUNK); * STATIC PROTOTYPES **********************/ -static void draw_circle_helper(int x_center, int y_center, nbgl_radius_t radiusIndex, uint8_t quarter, - color_t borderColor, color_t innerColor, color_t backgroundColor) { - uint8_t *quarter_buffer = NULL; - nbgl_area_t area = { - .bpp = NBGL_BPP_1, - .backgroundColor = backgroundColor - }; - - // radius is not supported - if (radiusIndex > RADIUS_48_PIXELS) { - return; - } - if (borderColor == innerColor) { - quarter_buffer = (uint8_t*)((nbgl_icon_details_t*)PIC(quarterDiscs[radiusIndex]))->bitmap; - } else { - quarter_buffer = (uint8_t*)((nbgl_icon_details_t*)PIC(quarterCircles[radiusIndex]))->bitmap; - } - area.width = area.height = radiusValues[radiusIndex]; - area.backgroundColor = backgroundColor; - if (quarter & BAGL_FILL_CIRCLE_3PI2_2PI) { // - area.x0 = x_center; - area.y0 = y_center; - nbgl_frontDrawImage(&area,quarter_buffer,BOTH_MIRRORS,borderColor); - } - if (quarter & BAGL_FILL_CIRCLE_PI_3PI2) { // - area.x0 = x_center-area.width; - area.y0 = y_center; - nbgl_frontDrawImage(&area,quarter_buffer,HORIZONTAL_MIRROR,borderColor); - } - if (quarter & BAGL_FILL_CIRCLE_0_PI2) { // - area.x0 = x_center; - area.y0 = y_center-area.width; - nbgl_frontDrawImage(&area,quarter_buffer,VERTICAL_MIRROR,borderColor); - } - if (quarter & BAGL_FILL_CIRCLE_PI2_PI) { // - area.x0 = x_center-area.width; - area.y0 = y_center-area.width; - nbgl_frontDrawImage(&area,quarter_buffer,NO_TRANSFORMATION,borderColor); - } +static void draw_circle_helper(int x_center, + int y_center, + nbgl_radius_t radiusIndex, + uint8_t quarter, + color_t borderColor, + color_t innerColor, + color_t backgroundColor) +{ + uint8_t *quarter_buffer = NULL; + nbgl_area_t area = {.bpp = NBGL_BPP_1, .backgroundColor = backgroundColor}; + + // radius is not supported + if (radiusIndex > RADIUS_48_PIXELS) { + return; + } + if (borderColor == innerColor) { + quarter_buffer + = (uint8_t *) ((nbgl_icon_details_t *) PIC(quarterDiscs[radiusIndex]))->bitmap; + } + else { + quarter_buffer + = (uint8_t *) ((nbgl_icon_details_t *) PIC(quarterCircles[radiusIndex]))->bitmap; + } + area.width = area.height = radiusValues[radiusIndex]; + area.backgroundColor = backgroundColor; + if (quarter & BAGL_FILL_CIRCLE_3PI2_2PI) { // + area.x0 = x_center; + area.y0 = y_center; + nbgl_frontDrawImage(&area, quarter_buffer, BOTH_MIRRORS, borderColor); + } + if (quarter & BAGL_FILL_CIRCLE_PI_3PI2) { // + area.x0 = x_center - area.width; + area.y0 = y_center; + nbgl_frontDrawImage(&area, quarter_buffer, HORIZONTAL_MIRROR, borderColor); + } + if (quarter & BAGL_FILL_CIRCLE_0_PI2) { // + area.x0 = x_center; + area.y0 = y_center - area.width; + nbgl_frontDrawImage(&area, quarter_buffer, VERTICAL_MIRROR, borderColor); + } + if (quarter & BAGL_FILL_CIRCLE_PI2_PI) { // + area.x0 = x_center - area.width; + area.y0 = y_center - area.width; + nbgl_frontDrawImage(&area, quarter_buffer, NO_TRANSFORMATION, borderColor); + } } /********************** @@ -151,216 +149,236 @@ static void draw_circle_helper(int x_center, int y_center, nbgl_radius_t radiusI **********************/ /** - * @brief This functions draws a rounded corners rectangle (without border), with the given parameters. + * @brief This functions draws a rounded corners rectangle (without border), with the given + * parameters. * - * @param area position, size and background color (outside of the rectangle) to use for the rectangle + * @param area position, size and background color (outside of the rectangle) to use for the + * rectangle * @param radiusIndex radius size * @param innerColor color to use for inside the rectangle */ -void nbgl_drawRoundedRect(const nbgl_area_t *area, nbgl_radius_t radiusIndex, color_t innerColor) { - nbgl_area_t rectArea; - uint8_t radius; - - LOG_DEBUG(DRAW_LOGGER,"nbgl_drawRoundedRect x0 = %d, y0 = %d, width =%d, height =%d\n",area->x0,area->y0,area->width,area->height); - - if (radiusIndex <= RADIUS_48_PIXELS) { - radius = radiusValues[radiusIndex]; - } - else if (radiusIndex == RADIUS_0_PIXELS) { - radius = 0; - } - else { - // radius not supported - LOG_WARN(DRAW_LOGGER,"nbgl_drawRoundedRect forbidden radius index =%d\n",radiusIndex); - return; - } - - // Draw main inner rectangle - rectArea.x0 = area->x0+radius; - rectArea.y0 = area->y0; - rectArea.width = area->width-(2*radius); - rectArea.height = area->height; - rectArea.backgroundColor = innerColor; - nbgl_frontDrawRect(&rectArea); - // special case when radius is null, just draw a rectangle - if (radiusIndex == RADIUS_0_PIXELS) { - return; - } - // Draw left inner rectangle - rectArea.x0 = area->x0; - rectArea.y0 = area->y0+radius; - rectArea.width = radius; - rectArea.height = area->height-(2*radius); - nbgl_frontDrawRect(&rectArea); - // Draw right inner rectangle - rectArea.x0 = area->x0+area->width-radius; - rectArea.y0 = area->y0+radius; - rectArea.width = radius; - rectArea.height = area->height-(2*radius); - nbgl_frontDrawRect(&rectArea); - - // Draw 4 quarters of disc - draw_circle_helper( area->x0+radius, - area->y0+radius, - radiusIndex, BAGL_FILL_CIRCLE_PI2_PI, - innerColor,//unused - innerColor, - area->backgroundColor); - draw_circle_helper( - area->x0+area->width-radius, - area->y0+radius, - radiusIndex, BAGL_FILL_CIRCLE_0_PI2, - innerColor,//unused - innerColor, - area->backgroundColor); - draw_circle_helper( - area->x0+radius, - area->y0+area->height-radius, - radiusIndex, BAGL_FILL_CIRCLE_PI_3PI2, - innerColor,//unused - innerColor, - area->backgroundColor); - draw_circle_helper( - area->x0+area->width-radius, - area->y0+area->height-radius, - radiusIndex, BAGL_FILL_CIRCLE_3PI2_2PI, - innerColor,//unused - innerColor, - area->backgroundColor); +void nbgl_drawRoundedRect(const nbgl_area_t *area, nbgl_radius_t radiusIndex, color_t innerColor) +{ + nbgl_area_t rectArea; + uint8_t radius; + + LOG_DEBUG(DRAW_LOGGER, + "nbgl_drawRoundedRect x0 = %d, y0 = %d, width =%d, height =%d\n", + area->x0, + area->y0, + area->width, + area->height); + + if (radiusIndex <= RADIUS_48_PIXELS) { + radius = radiusValues[radiusIndex]; + } + else if (radiusIndex == RADIUS_0_PIXELS) { + radius = 0; + } + else { + // radius not supported + LOG_WARN(DRAW_LOGGER, "nbgl_drawRoundedRect forbidden radius index =%d\n", radiusIndex); + return; + } + + // Draw main inner rectangle + rectArea.x0 = area->x0 + radius; + rectArea.y0 = area->y0; + rectArea.width = area->width - (2 * radius); + rectArea.height = area->height; + rectArea.backgroundColor = innerColor; + nbgl_frontDrawRect(&rectArea); + // special case when radius is null, just draw a rectangle + if (radiusIndex == RADIUS_0_PIXELS) { + return; + } + // Draw left inner rectangle + rectArea.x0 = area->x0; + rectArea.y0 = area->y0 + radius; + rectArea.width = radius; + rectArea.height = area->height - (2 * radius); + nbgl_frontDrawRect(&rectArea); + // Draw right inner rectangle + rectArea.x0 = area->x0 + area->width - radius; + rectArea.y0 = area->y0 + radius; + rectArea.width = radius; + rectArea.height = area->height - (2 * radius); + nbgl_frontDrawRect(&rectArea); + + // Draw 4 quarters of disc + draw_circle_helper(area->x0 + radius, + area->y0 + radius, + radiusIndex, + BAGL_FILL_CIRCLE_PI2_PI, + innerColor, // unused + innerColor, + area->backgroundColor); + draw_circle_helper(area->x0 + area->width - radius, + area->y0 + radius, + radiusIndex, + BAGL_FILL_CIRCLE_0_PI2, + innerColor, // unused + innerColor, + area->backgroundColor); + draw_circle_helper(area->x0 + radius, + area->y0 + area->height - radius, + radiusIndex, + BAGL_FILL_CIRCLE_PI_3PI2, + innerColor, // unused + innerColor, + area->backgroundColor); + draw_circle_helper(area->x0 + area->width - radius, + area->y0 + area->height - radius, + radiusIndex, + BAGL_FILL_CIRCLE_3PI2_2PI, + innerColor, // unused + innerColor, + area->backgroundColor); } /** * @brief This functions draws a rounded corners rectangle with a border, with the given parameters. * - * @param area position, size and background color (outside of the rectangle) to use for the rectangle + * @param area position, size and background color (outside of the rectangle) to use for the + * rectangle * @param radiusIndex radius size * @param stroke thickness of border (fixed to 2) * @param innerColor color to use for inside the rectangle * @param borderColor color to use for the border */ -void nbgl_drawRoundedBorderedRect(const nbgl_area_t *area, nbgl_radius_t radiusIndex, uint8_t stroke, - color_t innerColor, color_t borderColor) { - uint8_t maskTop, maskBottom; - uint8_t radius; - nbgl_area_t rectArea; - - LOG_DEBUG(DRAW_LOGGER,"nbgl_drawRoundedBorderedRect: innerColor = %d, borderColor = %d, backgroundColor=%d\n",innerColor,borderColor,area->backgroundColor); - - if (radiusIndex <= RADIUS_48_PIXELS) { - radius = radiusValues[radiusIndex]; - } - else if (radiusIndex == RADIUS_0_PIXELS) { - radius = 0; - } - else { - // radius not supported - LOG_WARN(DRAW_LOGGER,"nbgl_drawRoundedBorderedRect forbidden radius index =%d\n",radiusIndex); - return; - } - rectArea.backgroundColor = innerColor; - - // special case, when border_color == inner_color == background_color, just draw a rectangle - if ((innerColor == borderColor) && (borderColor == area->backgroundColor )) { - rectArea.x0 = area->x0; - rectArea.y0 = area->y0; - rectArea.width = area->width; - rectArea.height = area->height; - nbgl_frontDrawRect(&rectArea); - return; - } - // Draw 3 rectangles - if ((2*radius)width) { - rectArea.x0 = area->x0+radius; - rectArea.y0 = area->y0; - rectArea.width = area->width-(2*radius); - rectArea.height = area->height; - nbgl_frontDrawRect(&rectArea); - } - // special case when radius is null, left and right rectangles are not necessary - if (radiusIndex <= RADIUS_48_PIXELS) { - if ((2*radius)height) { - rectArea.x0 = area->x0; - rectArea.y0 = area->y0+radius; - rectArea.width = radius; - rectArea.height = area->height-(2*radius); - nbgl_frontDrawRect(&rectArea); - rectArea.x0 = area->x0+area->width-radius; - rectArea.y0 = area->y0+radius; - nbgl_frontDrawRect(&rectArea); - } - } - // border - // 4 rectangles (with last pixel of each corner not set) - if (stroke == 1) { - maskTop = 0x1; - maskBottom = 0x8; - } - else if (stroke == 2) { - maskTop = 0x3; - maskBottom = 0xC; - } - else if (stroke == 3) { - maskTop = 0x7; - maskBottom = 0xE; - } - else if (stroke == 4) { - maskTop = 0xF; - maskBottom = 0xF; - } - else { - LOG_WARN(DRAW_LOGGER,"nbgl_drawRoundedBorderedRect forbidden stroke=%d\n",stroke); - return; - } - rectArea.x0 = area->x0+radius; - rectArea.y0 = area->y0; - rectArea.width = area->width-2*radius; - rectArea.height = 4; - nbgl_frontDrawHorizontalLine(&rectArea, maskTop,borderColor); // bottom - rectArea.x0 = area->x0+radius; - rectArea.y0 = area->y0+area->height-4; - nbgl_frontDrawHorizontalLine(&rectArea, maskBottom,borderColor); // bottom - if ((2*radius)height) { - rectArea.x0 = area->x0; - rectArea.y0 = area->y0+radius; - rectArea.width = stroke; - rectArea.height = area->height-2*radius; - rectArea.backgroundColor = borderColor; - nbgl_frontDrawRect(&rectArea); // left - rectArea.x0 = area->x0+area->width-stroke; - nbgl_frontDrawRect(&rectArea); // right - } - - if (radiusIndex <= RADIUS_48_PIXELS) { - // Draw 4 quarters of circles - draw_circle_helper( - area->x0+radius, - area->y0+radius, - radiusIndex, BAGL_FILL_CIRCLE_PI2_PI, - borderColor, - innerColor, - area->backgroundColor); - draw_circle_helper( - area->x0+area->width-radius, - area->y0+radius, - radiusIndex, BAGL_FILL_CIRCLE_0_PI2, - borderColor, - innerColor, - area->backgroundColor); - draw_circle_helper( - area->x0+radius, - area->y0+area->height-radius, - radiusIndex, BAGL_FILL_CIRCLE_PI_3PI2, - borderColor, - innerColor, - area->backgroundColor); - draw_circle_helper( - area->x0+area->width-radius, - area->y0+area->height-radius, - radiusIndex, BAGL_FILL_CIRCLE_3PI2_2PI, - borderColor, - innerColor, - area->backgroundColor); - } +void nbgl_drawRoundedBorderedRect(const nbgl_area_t *area, + nbgl_radius_t radiusIndex, + uint8_t stroke, + color_t innerColor, + color_t borderColor) +{ + uint8_t maskTop, maskBottom; + uint8_t radius; + nbgl_area_t rectArea; + + LOG_DEBUG( + DRAW_LOGGER, + "nbgl_drawRoundedBorderedRect: innerColor = %d, borderColor = %d, backgroundColor=%d\n", + innerColor, + borderColor, + area->backgroundColor); + + if (radiusIndex <= RADIUS_48_PIXELS) { + radius = radiusValues[radiusIndex]; + } + else if (radiusIndex == RADIUS_0_PIXELS) { + radius = 0; + } + else { + // radius not supported + LOG_WARN( + DRAW_LOGGER, "nbgl_drawRoundedBorderedRect forbidden radius index =%d\n", radiusIndex); + return; + } + rectArea.backgroundColor = innerColor; + + // special case, when border_color == inner_color == background_color, just draw a rectangle + if ((innerColor == borderColor) && (borderColor == area->backgroundColor)) { + rectArea.x0 = area->x0; + rectArea.y0 = area->y0; + rectArea.width = area->width; + rectArea.height = area->height; + nbgl_frontDrawRect(&rectArea); + return; + } + // Draw 3 rectangles + if ((2 * radius) < area->width) { + rectArea.x0 = area->x0 + radius; + rectArea.y0 = area->y0; + rectArea.width = area->width - (2 * radius); + rectArea.height = area->height; + nbgl_frontDrawRect(&rectArea); + } + // special case when radius is null, left and right rectangles are not necessary + if (radiusIndex <= RADIUS_48_PIXELS) { + if ((2 * radius) < area->height) { + rectArea.x0 = area->x0; + rectArea.y0 = area->y0 + radius; + rectArea.width = radius; + rectArea.height = area->height - (2 * radius); + nbgl_frontDrawRect(&rectArea); + rectArea.x0 = area->x0 + area->width - radius; + rectArea.y0 = area->y0 + radius; + nbgl_frontDrawRect(&rectArea); + } + } + // border + // 4 rectangles (with last pixel of each corner not set) + if (stroke == 1) { + maskTop = 0x1; + maskBottom = 0x8; + } + else if (stroke == 2) { + maskTop = 0x3; + maskBottom = 0xC; + } + else if (stroke == 3) { + maskTop = 0x7; + maskBottom = 0xE; + } + else if (stroke == 4) { + maskTop = 0xF; + maskBottom = 0xF; + } + else { + LOG_WARN(DRAW_LOGGER, "nbgl_drawRoundedBorderedRect forbidden stroke=%d\n", stroke); + return; + } + rectArea.x0 = area->x0 + radius; + rectArea.y0 = area->y0; + rectArea.width = area->width - 2 * radius; + rectArea.height = 4; + nbgl_frontDrawHorizontalLine(&rectArea, maskTop, borderColor); // bottom + rectArea.x0 = area->x0 + radius; + rectArea.y0 = area->y0 + area->height - 4; + nbgl_frontDrawHorizontalLine(&rectArea, maskBottom, borderColor); // bottom + if ((2 * radius) < area->height) { + rectArea.x0 = area->x0; + rectArea.y0 = area->y0 + radius; + rectArea.width = stroke; + rectArea.height = area->height - 2 * radius; + rectArea.backgroundColor = borderColor; + nbgl_frontDrawRect(&rectArea); // left + rectArea.x0 = area->x0 + area->width - stroke; + nbgl_frontDrawRect(&rectArea); // right + } + + if (radiusIndex <= RADIUS_48_PIXELS) { + // Draw 4 quarters of circles + draw_circle_helper(area->x0 + radius, + area->y0 + radius, + radiusIndex, + BAGL_FILL_CIRCLE_PI2_PI, + borderColor, + innerColor, + area->backgroundColor); + draw_circle_helper(area->x0 + area->width - radius, + area->y0 + radius, + radiusIndex, + BAGL_FILL_CIRCLE_0_PI2, + borderColor, + innerColor, + area->backgroundColor); + draw_circle_helper(area->x0 + radius, + area->y0 + area->height - radius, + radiusIndex, + BAGL_FILL_CIRCLE_PI_3PI2, + borderColor, + innerColor, + area->backgroundColor); + draw_circle_helper(area->x0 + area->width - radius, + area->y0 + area->height - radius, + radiusIndex, + BAGL_FILL_CIRCLE_3PI2_2PI, + borderColor, + innerColor, + area->backgroundColor); + } } /** @@ -373,12 +391,14 @@ void nbgl_drawRoundedBorderedRect(const nbgl_area_t *area, nbgl_radius_t radiusI * @param color_map Color map applied to icon * @param icon Icon details structure to draw */ -void nbgl_drawIcon(nbgl_area_t *area, nbgl_color_map_t color_map, const nbgl_icon_details_t *icon) { - if (icon->isFile) { - nbgl_frontDrawImageFile(area, icon->bitmap, color_map, ramBuffer); - } else { - nbgl_frontDrawImage(area, icon->bitmap, NO_TRANSFORMATION, color_map); - } +void nbgl_drawIcon(nbgl_area_t *area, nbgl_color_map_t color_map, const nbgl_icon_details_t *icon) +{ + if (icon->isFile) { + nbgl_frontDrawImageFile(area, icon->bitmap, color_map, ramBuffer); + } + else { + nbgl_frontDrawImage(area, icon->bitmap, NO_TRANSFORMATION, color_map); + } } /** @@ -388,20 +408,23 @@ void nbgl_drawIcon(nbgl_area_t *area, nbgl_color_map_t color_map, const nbgl_ico * @param charId id of the character */ -static uint16_t get_bitmap_byte_cnt(const nbgl_font_t *font, uint8_t charId) { - if ((charId < font->first_char) || (charId > font->last_char)) { +static uint16_t get_bitmap_byte_cnt(const nbgl_font_t *font, uint8_t charId) +{ + if ((charId < font->first_char) || (charId > font->last_char)) { + return 0; + } + + uint16_t baseId = charId - font->first_char; + if (charId < font->last_char) { + nbgl_font_character_t *character = (nbgl_font_character_t *) PIC(&font->characters[baseId]); + nbgl_font_character_t *nextCharacter + = (nbgl_font_character_t *) PIC(&font->characters[baseId + 1]); + return (nextCharacter->bitmap_offset - character->bitmap_offset); + } + else if (charId == font->last_char) { + return (font->bitmap_len - font->characters[baseId].bitmap_offset); + } return 0; - } - - uint16_t baseId = charId - font->first_char; - if (charId < font->last_char) { - nbgl_font_character_t *character = (nbgl_font_character_t *)PIC(&font->characters[baseId]); - nbgl_font_character_t *nextCharacter = (nbgl_font_character_t *)PIC(&font->characters[baseId+1]); - return (nextCharacter->bitmap_offset - character->bitmap_offset); - } else if (charId == font->last_char) { - return (font->bitmap_len - font->characters[baseId].bitmap_offset); - } - return 0; } /** @@ -413,199 +436,219 @@ static uint16_t get_bitmap_byte_cnt(const nbgl_font_t *font, uint8_t charId) { * @param fontId font to be used * @param fontColor color to use for font */ -void nbgl_drawText(const nbgl_area_t *area, const char* text, uint16_t textLen, nbgl_font_id_e fontId, color_t fontColor) { - // text is a series of characters, each character being a bitmap - // we need to align bitmaps on width multiple of 4 limitation. - int16_t x = area->x0; - nbgl_area_t rectArea; - const nbgl_font_t *font = nbgl_getFont(fontId); - - LOG_DEBUG(DRAW_LOGGER,"nbgl_drawText: x0 = %d, y0 = %d, w = %d, h = %d, fontColor = %d, backgroundColor=%d, text = %s\n",area->x0, area->y0, area->width,area->height,fontColor,area->backgroundColor, text); +void nbgl_drawText(const nbgl_area_t *area, + const char *text, + uint16_t textLen, + nbgl_font_id_e fontId, + color_t fontColor) +{ + // text is a series of characters, each character being a bitmap + // we need to align bitmaps on width multiple of 4 limitation. + int16_t x = area->x0; + nbgl_area_t rectArea; + const nbgl_font_t *font = nbgl_getFont(fontId); + + LOG_DEBUG(DRAW_LOGGER, + "nbgl_drawText: x0 = %d, y0 = %d, w = %d, h = %d, fontColor = %d, " + "backgroundColor=%d, text = %s\n", + area->x0, + area->y0, + area->width, + area->height, + fontColor, + area->backgroundColor, + text); #ifdef HAVE_UNICODE_SUPPORT - nbgl_unicode_ctx_t *unicode_ctx = nbgl_getUnicodeFont(fontId); -#endif // HAVE_UNICODE_SUPPORT - - rectArea.backgroundColor = area->backgroundColor; - rectArea.bpp = (nbgl_bpp_t) font->bpp; - - while (textLen>0) { - nbgl_font_character_t *character; - uint8_t char_width; - uint32_t unicode; - bool is_unicode; - uint8_t *char_buffer; - int16_t char_x_min; - int16_t char_y_min; - int16_t char_x_max; - int16_t char_y_max; - uint16_t char_byte_cnt; - uint8_t encoding; - uint8_t nb_skipped_bytes; - - unicode = nbgl_popUnicodeChar((const uint8_t **)&text, &textLen, &is_unicode); - - if (is_unicode) { + nbgl_unicode_ctx_t *unicode_ctx = nbgl_getUnicodeFont(fontId); +#endif // HAVE_UNICODE_SUPPORT + + rectArea.backgroundColor = area->backgroundColor; + rectArea.bpp = (nbgl_bpp_t) font->bpp; + + while (textLen > 0) { + nbgl_font_character_t *character; + uint8_t char_width; + uint32_t unicode; + bool is_unicode; + uint8_t *char_buffer; + int16_t char_x_min; + int16_t char_y_min; + int16_t char_x_max; + int16_t char_y_max; + uint16_t char_byte_cnt; + uint8_t encoding; + uint8_t nb_skipped_bytes; + + unicode = nbgl_popUnicodeChar((const uint8_t **) &text, &textLen, &is_unicode); + + if (is_unicode) { #ifdef HAVE_UNICODE_SUPPORT - const nbgl_font_unicode_character_t *unicodeCharacter = nbgl_getUnicodeFontCharacter(unicode); - // if not supported char, go to next one - if (unicodeCharacter == NULL) { - continue; - } - char_width = unicodeCharacter->width; + const nbgl_font_unicode_character_t *unicodeCharacter + = nbgl_getUnicodeFontCharacter(unicode); + // if not supported char, go to next one + if (unicodeCharacter == NULL) { + continue; + } + char_width = unicodeCharacter->width; #if defined(HAVE_LANGUAGE_PACK) - char_buffer = (uint8_t*)unicode_ctx->bitmap; - char_buffer+= unicodeCharacter->bitmap_offset; - - char_x_max = char_width; - char_y_max = unicode_ctx->font->height; - - if (!unicode_ctx->font->crop) { - // Take in account the skipped bytes, if any - nb_skipped_bytes = (unicodeCharacter->x_min_offset & 7) << 3; - nb_skipped_bytes |= unicodeCharacter->y_min_offset & 7; - char_x_min = 0; - char_y_min = 0; - } else { - nb_skipped_bytes = 0; - char_x_min = (uint16_t)unicodeCharacter->x_min_offset; - char_y_min = unicode_ctx->font->y_min; - char_y_min += (uint16_t)unicodeCharacter->y_min_offset * 4; - char_x_max -= (uint16_t)unicodeCharacter->x_max_offset; - char_y_max -= (uint16_t)unicodeCharacter->y_max_offset * 4; - } - - char_byte_cnt = nbgl_getUnicodeFontCharacterByteCount(); - encoding = unicodeCharacter->encoding; -#endif //defined(HAVE_LANGUAGE_PACK) -#else // HAVE_UNICODE_SUPPORT - continue; -#endif // HAVE_UNICODE_SUPPORT + char_buffer = (uint8_t *) unicode_ctx->bitmap; + char_buffer += unicodeCharacter->bitmap_offset; + + char_x_max = char_width; + char_y_max = unicode_ctx->font->height; + + if (!unicode_ctx->font->crop) { + // Take in account the skipped bytes, if any + nb_skipped_bytes = (unicodeCharacter->x_min_offset & 7) << 3; + nb_skipped_bytes |= unicodeCharacter->y_min_offset & 7; + char_x_min = 0; + char_y_min = 0; + } + else { + nb_skipped_bytes = 0; + char_x_min = (uint16_t) unicodeCharacter->x_min_offset; + char_y_min = unicode_ctx->font->y_min; + char_y_min += (uint16_t) unicodeCharacter->y_min_offset * 4; + char_x_max -= (uint16_t) unicodeCharacter->x_max_offset; + char_y_max -= (uint16_t) unicodeCharacter->y_max_offset * 4; + } + + char_byte_cnt = nbgl_getUnicodeFontCharacterByteCount(); + encoding = unicodeCharacter->encoding; +#endif // defined(HAVE_LANGUAGE_PACK) +#else // HAVE_UNICODE_SUPPORT + continue; +#endif // HAVE_UNICODE_SUPPORT + } + else { + // if not supported char, go to next one + if ((unicode < font->first_char) || (unicode > font->last_char)) { + continue; + } + character + = (nbgl_font_character_t *) PIC(&font->characters[unicode - font->first_char]); + char_buffer = (uint8_t *) PIC(&font->bitmap[character->bitmap_offset]); + char_width = character->width; + encoding = character->encoding; + + char_x_max = char_width; + char_y_max = font->height; + + if (!font->crop) { + // Take in account the skipped bytes, if any + nb_skipped_bytes = (character->x_min_offset & 7) << 3; + nb_skipped_bytes |= character->y_min_offset & 7; + char_x_min = 0; + char_y_min = 0; + } + else { + nb_skipped_bytes = 0; + char_x_min = (uint16_t) character->x_min_offset; + char_y_min = font->y_min; + char_y_min += (uint16_t) character->y_min_offset * 4; + char_x_max -= (uint16_t) character->x_max_offset; + char_y_max -= (uint16_t) character->y_max_offset * 4; + } + + char_byte_cnt = get_bitmap_byte_cnt(font, unicode); + } + + // Render character + rectArea.x0 = x + char_x_min; + rectArea.y0 = area->y0 + char_y_min; + rectArea.height = (char_y_max - char_y_min); + rectArea.width = (char_x_max - char_x_min); + + // If char_byte_cnt = 0, call nbgl_frontDrawImageRle to let speculos notice + // a space character was 'displayed' + if (!char_byte_cnt || encoding == 1) { + nbgl_frontDrawImageRle( + &rectArea, char_buffer, char_byte_cnt, fontColor, nb_skipped_bytes); + } + else { + nbgl_frontDrawImage(&rectArea, char_buffer, NO_TRANSFORMATION, fontColor); + } + x += char_width; } - else { - // if not supported char, go to next one - if ((unicode < font->first_char) || (unicode > font->last_char)) { - continue; - } - character = (nbgl_font_character_t *)PIC(&font->characters[unicode-font->first_char]); - char_buffer = (uint8_t *)PIC(&font->bitmap[character->bitmap_offset]); - char_width = character->width; - encoding = character->encoding; - - char_x_max = char_width; - char_y_max = font->height; - - if (!font->crop) { - // Take in account the skipped bytes, if any - nb_skipped_bytes = (character->x_min_offset & 7) << 3; - nb_skipped_bytes |= character->y_min_offset & 7; - char_x_min = 0; - char_y_min = 0; - } else { - nb_skipped_bytes = 0; - char_x_min = (uint16_t)character->x_min_offset; - char_y_min = font->y_min; - char_y_min += (uint16_t)character->y_min_offset * 4; - char_x_max -= (uint16_t)character->x_max_offset; - char_y_max -= (uint16_t)character->y_max_offset * 4; - } - - char_byte_cnt = get_bitmap_byte_cnt(font, unicode); - } - - // Render character - rectArea.x0 = x + char_x_min; - rectArea.y0 = area->y0 + char_y_min; - rectArea.height = (char_y_max - char_y_min); - rectArea.width = (char_x_max -char_x_min); - - // If char_byte_cnt = 0, call nbgl_frontDrawImageRle to let speculos notice - // a space character was 'displayed' - if (!char_byte_cnt || encoding == 1) { - nbgl_frontDrawImageRle( - &rectArea, char_buffer, char_byte_cnt, fontColor, nb_skipped_bytes); - } else { - nbgl_frontDrawImage(&rectArea, char_buffer, NO_TRANSFORMATION, fontColor); - } - x+=char_width; - } } #ifdef NBGL_QRCODE static void nbgl_frontDrawQrInternal(const nbgl_area_t *area, color_t foregroundColor) { - int size = qrcodegen_getSize(qrcode); - uint16_t idx = 0; - - nbgl_area_t qrArea = - { - .x0 = area->x0, - .y0 = area->y0, - .backgroundColor = area->backgroundColor, - // QR codes are 1 BPP only - .bpp = NBGL_BPP_1 - }; - if (size == QR_V4_NB_PIX_SIZE) { - // for each point of the V4 QR code, paint 64 pixels in image (8 in width, 8 in height) - qrArea.width = 2; - qrArea.height = QR_PIXEL_WIDTH_HEIGHT*2*size; - // paint a column of 2*size pixels in width by 8 pixels in height - for (int x = 0; x < size; x++) { - idx = 0; - for (int y = 0; y < size; y++) { - // draw 2 columns at once - QrDrawBuffer[idx] = qrcodegen_getModule(qrcode, x, y)?0xFF:0x00; - QrDrawBuffer[idx+QR_V4_NB_PIX_SIZE] = QrDrawBuffer[idx]; - idx += 1; - } - nbgl_frontDrawImage(&qrArea, QrDrawBuffer, NO_TRANSFORMATION, foregroundColor); - qrArea.x0 += 2; - nbgl_frontDrawImage(&qrArea, QrDrawBuffer, NO_TRANSFORMATION, foregroundColor); - qrArea.x0 += 2; - nbgl_frontDrawImage(&qrArea, QrDrawBuffer, NO_TRANSFORMATION, foregroundColor); - qrArea.x0 += 2; - nbgl_frontDrawImage(&qrArea, QrDrawBuffer, NO_TRANSFORMATION, foregroundColor); - qrArea.x0 += 2; - } - } - else { - // for each point of the V10 QR code, paint 16 pixels in image (4 in width, 4 in height) - qrArea.width = QR_PIXEL_WIDTH_HEIGHT*size; - qrArea.height = QR_PIXEL_WIDTH_HEIGHT; - // paint a line of 4*size pixels in width by 4 pixels in height - for (int y = 0; y < size; y++) { - idx = 0; - for (int x = 0; x < size; x++) { - memset(&QrDrawBuffer[idx], qrcodegen_getModule(qrcode, x, y)?0xFF:0x00, 2); - idx += 2; - } - nbgl_frontDrawImage(&qrArea, QrDrawBuffer, NO_TRANSFORMATION, foregroundColor); - qrArea.y0 += QR_PIXEL_WIDTH_HEIGHT; - } - } + int size = qrcodegen_getSize(qrcode); + uint16_t idx = 0; + + nbgl_area_t qrArea = {.x0 = area->x0, + .y0 = area->y0, + .backgroundColor = area->backgroundColor, + // QR codes are 1 BPP only + .bpp = NBGL_BPP_1}; + if (size == QR_V4_NB_PIX_SIZE) { + // for each point of the V4 QR code, paint 64 pixels in image (8 in width, 8 in height) + qrArea.width = 2; + qrArea.height = QR_PIXEL_WIDTH_HEIGHT * 2 * size; + // paint a column of 2*size pixels in width by 8 pixels in height + for (int x = 0; x < size; x++) { + idx = 0; + for (int y = 0; y < size; y++) { + // draw 2 columns at once + QrDrawBuffer[idx] = qrcodegen_getModule(qrcode, x, y) ? 0xFF : 0x00; + QrDrawBuffer[idx + QR_V4_NB_PIX_SIZE] = QrDrawBuffer[idx]; + idx += 1; + } + nbgl_frontDrawImage(&qrArea, QrDrawBuffer, NO_TRANSFORMATION, foregroundColor); + qrArea.x0 += 2; + nbgl_frontDrawImage(&qrArea, QrDrawBuffer, NO_TRANSFORMATION, foregroundColor); + qrArea.x0 += 2; + nbgl_frontDrawImage(&qrArea, QrDrawBuffer, NO_TRANSFORMATION, foregroundColor); + qrArea.x0 += 2; + nbgl_frontDrawImage(&qrArea, QrDrawBuffer, NO_TRANSFORMATION, foregroundColor); + qrArea.x0 += 2; + } + } + else { + // for each point of the V10 QR code, paint 16 pixels in image (4 in width, 4 in height) + qrArea.width = QR_PIXEL_WIDTH_HEIGHT * size; + qrArea.height = QR_PIXEL_WIDTH_HEIGHT; + // paint a line of 4*size pixels in width by 4 pixels in height + for (int y = 0; y < size; y++) { + idx = 0; + for (int x = 0; x < size; x++) { + memset(&QrDrawBuffer[idx], qrcodegen_getModule(qrcode, x, y) ? 0xFF : 0x00, 2); + idx += 2; + } + nbgl_frontDrawImage(&qrArea, QrDrawBuffer, NO_TRANSFORMATION, foregroundColor); + qrArea.y0 += QR_PIXEL_WIDTH_HEIGHT; + } + } } /** - * @brief Draws the given text into a V10 QR code (QR code version is fixed using qrcodegen_VERSION_MIN/qrcodegen_VERSION_MAX in qrcodegen.h) + * @brief Draws the given text into a V10 QR code (QR code version is fixed using + * qrcodegen_VERSION_MIN/qrcodegen_VERSION_MAX in qrcodegen.h) * - * @note y0 and height must be multiple 4 pixels, and background color is applied to 0's in 1BPP bitmap. + * @note y0 and height must be multiple 4 pixels, and background color is applied to 0's in 1BPP + * bitmap. * * @param area position, size and color of the QR code to draw * @param version version of QR Code (4, 10, ...) * @param text text to encode * @param foregroundColor color to be applied to the 1's in QR code */ -void nbgl_drawQrCode(const nbgl_area_t *area, uint8_t version, const char *text, color_t foregroundColor) +void nbgl_drawQrCode(const nbgl_area_t *area, + uint8_t version, + const char *text, + color_t foregroundColor) { + bool ok = qrcodegen_encodeText( + text, tempBuffer, qrcode, qrcodegen_Ecc_LOW, version, version, qrcodegen_Mask_AUTO, true); - bool ok = qrcodegen_encodeText(text, tempBuffer, qrcode, qrcodegen_Ecc_LOW, - version, version, qrcodegen_Mask_AUTO, true); - - if (ok) { - nbgl_frontDrawQrInternal(area, foregroundColor); - } - else { - LOG_WARN(DRAW_LOGGER,"Impossible to draw QRCode text %s with version %d\n",text, version); - } + if (ok) { + nbgl_frontDrawQrInternal(area, foregroundColor); + } + else { + LOG_WARN(DRAW_LOGGER, "Impossible to draw QRCode text %s with version %d\n", text, version); + } } -#endif // NBGL_QRCODE +#endif // NBGL_QRCODE diff --git a/lib_nbgl/src/nbgl_fonts.c b/lib_nbgl/src/nbgl_fonts.c index 8bc90238c..b8e6926b8 100644 --- a/lib_nbgl/src/nbgl_fonts.c +++ b/lib_nbgl/src/nbgl_fonts.c @@ -15,17 +15,16 @@ #include "os_pic.h" #if defined(HAVE_LANGUAGE_PACK) #include "ux_loc.h" -#endif //defined(HAVE_LANGUAGE_PACK) +#endif // defined(HAVE_LANGUAGE_PACK) /********************* * DEFINES *********************/ -#define PIC_FONT(x) ((nbgl_font_t const *)PIC(x)) +#define PIC_FONT(x) ((nbgl_font_t const *) PIC(x)) #define BAGL_FONT_ID_MASK 0x0FFF #define IS_WORD_DELIM(c) (c == ' ' || c == '\n' || c == '\b' || c == '\f' || c == '-' || c == '_') - /********************** * TYPEDEFS **********************/ @@ -35,7 +34,7 @@ **********************/ #ifdef HAVE_UNICODE_SUPPORT static nbgl_unicode_ctx_t unicodeCtx = {0}; -#endif // HAVE_UNICODE_SUPPORT +#endif // HAVE_UNICODE_SUPPORT /********************** * VARIABLES @@ -43,8 +42,7 @@ static nbgl_unicode_ctx_t unicodeCtx = {0}; #if defined(HAVE_LANGUAGE_PACK) extern const LANGUAGE_PACK *language_pack; -#endif //defined(HAVE_LANGUAGE_PACK) - +#endif // defined(HAVE_LANGUAGE_PACK) #if defined(BOLOS_OS_UPGRADER_APP) #include "nbgl_font_hmalpha_mono_medium_32.inc" @@ -55,29 +53,30 @@ extern const LANGUAGE_PACK *language_pack; #include "nbgl_font_inter_semibold_24_1bpp.inc" #include "nbgl_font_inter_medium_32_1bpp.inc" -const nbgl_font_t* const C_nbgl_fonts[] = { +const nbgl_font_t *const C_nbgl_fonts[] = { #include "nbgl_font_rom_struct.inc" - }; -const unsigned int C_nbgl_fonts_count = sizeof(C_nbgl_fonts)/sizeof(C_nbgl_fonts[0]); +const unsigned int C_nbgl_fonts_count = sizeof(C_nbgl_fonts) / sizeof(C_nbgl_fonts[0]); #endif #if (defined(HAVE_BOLOS) && !defined(BOLOS_OS_UPGRADER_APP)) #if !defined(HAVE_LANGUAGE_PACK) -const nbgl_font_unicode_t* const C_nbgl_fonts_unicode[] = { +const nbgl_font_unicode_t *const C_nbgl_fonts_unicode[] = { #include "nbgl_font_unicode_rom_struct.inc" }; // All Unicode fonts MUST have the same number of characters! -const unsigned int C_unicode_characters_count = (sizeof(charactersOPEN_SANS_REGULAR_11PX_UNICODE)/sizeof(charactersOPEN_SANS_REGULAR_11PX_UNICODE[0])); +const unsigned int C_unicode_characters_count + = (sizeof(charactersOPEN_SANS_REGULAR_11PX_UNICODE) + / sizeof(charactersOPEN_SANS_REGULAR_11PX_UNICODE[0])); -#endif //!defined(HAVE_LANGUAGE_PACK) -#endif //HAVE_BOLOS +#endif //! defined(HAVE_LANGUAGE_PACK) +#endif // HAVE_BOLOS /********************** * STATIC PROTOTYPES @@ -94,25 +93,27 @@ const unsigned int C_unicode_characters_count = (sizeof(charactersOPEN_SANS_REGU * @return the found font or NULL */ #if defined(BOLOS_OS_UPGRADER_APP) -const nbgl_font_t *nbgl_getFont(nbgl_font_id_e fontId) { - unsigned int i = C_nbgl_fonts_count; - fontId &= BAGL_FONT_ID_MASK; - - while(i--) { - // font id match this entry (non indexed array) - if (PIC_FONT(C_nbgl_fonts[i])->font_id == fontId) { - return PIC_FONT(C_nbgl_fonts[i]); +const nbgl_font_t *nbgl_getFont(nbgl_font_id_e fontId) +{ + unsigned int i = C_nbgl_fonts_count; + fontId &= BAGL_FONT_ID_MASK; + + while (i--) { + // font id match this entry (non indexed array) + if (PIC_FONT(C_nbgl_fonts[i])->font_id == fontId) { + return PIC_FONT(C_nbgl_fonts[i]); + } } - } - // id not found - return NULL; + // id not found + return NULL; } #else -const nbgl_font_t *nbgl_getFont(nbgl_font_id_e fontId) { - return nbgl_font_getFont(fontId); +const nbgl_font_t *nbgl_getFont(nbgl_font_id_e fontId) +{ + return nbgl_font_getFont(fontId); } -#endif // BOLOS_OS_UPGRADER_APP +#endif // BOLOS_OS_UPGRADER_APP /** * @brief Get the coming unicode value on the given UTF-8 string. If the value is a simple ASCII * character, is_unicode is set to false. @@ -122,47 +123,50 @@ const nbgl_font_t *nbgl_getFont(nbgl_font_id_e fontId) { * @param is_unicode (out) set to true if it's a real unicode (not ASCII) * @return unicode (or ascii-7) value of the found character */ -uint32_t nbgl_popUnicodeChar(const uint8_t **text, uint16_t *textLen, bool *is_unicode) { - const uint8_t *txt = *text; - uint8_t cur_char = *txt++; - uint32_t unicode; - - *is_unicode = true; - // Handle UTF-8 decoding (RFC3629): (https://www.ietf.org/rfc/rfc3629.txt - // Char. number range | UTF-8 octet sequence - // (hexadecimal) | (binary) - // --------------------+--------------------------------------------- - // 0000 0000-0000 007F | 0xxxxxxx - // 0000 0080-0000 07FF | 110xxxxx 10xxxxxx - // 0000 0800-0000 FFFF | 1110xxxx 10xxxxxx 10xxxxxx - // 0001 0000-0010 FFFF | 11110xxx 10xxxxxx 10xxxxxx 10xxxxxx - - // 4 bytes UTF-8, Unicode 0x1000 to 0x1FFFF - if ((cur_char >= 0xF0) && (*textLen >= 4)) { - unicode = (cur_char & 0x07) << 18; - unicode |= (*txt++ & 0x3F) << 12; - unicode |= (*txt++ & 0x3F) << 6; - unicode |= (*txt++ & 0x3F); - - // 3 bytes, from 0x800 to 0xFFFF - } else if ((cur_char >= 0xE0) && (*textLen >= 3)) { - unicode = (cur_char & 0x0F) << 12; - unicode |= (*txt++ & 0x3F) << 6; - unicode |= (*txt++ & 0x3F); - - // 2 bytes UTF-8, Unicode 0x80 to 0x7FF - // (0xC0 & 0xC1 are unused and can be used to store something else) - } else if ((cur_char >= 0xC2) && (*textLen >= 2)) { - unicode = (cur_char & 0x1F) << 6; - unicode |= (*txt++ & 0x3F); - - } else { - *is_unicode = false; - unicode = cur_char; - } - *textLen = *textLen-(txt - *text); - *text = txt; - return unicode; +uint32_t nbgl_popUnicodeChar(const uint8_t **text, uint16_t *textLen, bool *is_unicode) +{ + const uint8_t *txt = *text; + uint8_t cur_char = *txt++; + uint32_t unicode; + + *is_unicode = true; + // Handle UTF-8 decoding (RFC3629): (https://www.ietf.org/rfc/rfc3629.txt + // Char. number range | UTF-8 octet sequence + // (hexadecimal) | (binary) + // --------------------+--------------------------------------------- + // 0000 0000-0000 007F | 0xxxxxxx + // 0000 0080-0000 07FF | 110xxxxx 10xxxxxx + // 0000 0800-0000 FFFF | 1110xxxx 10xxxxxx 10xxxxxx + // 0001 0000-0010 FFFF | 11110xxx 10xxxxxx 10xxxxxx 10xxxxxx + + // 4 bytes UTF-8, Unicode 0x1000 to 0x1FFFF + if ((cur_char >= 0xF0) && (*textLen >= 4)) { + unicode = (cur_char & 0x07) << 18; + unicode |= (*txt++ & 0x3F) << 12; + unicode |= (*txt++ & 0x3F) << 6; + unicode |= (*txt++ & 0x3F); + + // 3 bytes, from 0x800 to 0xFFFF + } + else if ((cur_char >= 0xE0) && (*textLen >= 3)) { + unicode = (cur_char & 0x0F) << 12; + unicode |= (*txt++ & 0x3F) << 6; + unicode |= (*txt++ & 0x3F); + + // 2 bytes UTF-8, Unicode 0x80 to 0x7FF + // (0xC0 & 0xC1 are unused and can be used to store something else) + } + else if ((cur_char >= 0xC2) && (*textLen >= 2)) { + unicode = (cur_char & 0x1F) << 6; + unicode |= (*txt++ & 0x3F); + } + else { + *is_unicode = false; + unicode = cur_char; + } + *textLen = *textLen - (txt - *text); + *text = txt; + return unicode; } /** @@ -173,31 +177,34 @@ uint32_t nbgl_popUnicodeChar(const uint8_t **text, uint16_t *textLen, bool *is_u * @param is_unicode if true, is unicode * @return the width in pixels of the char */ -static uint8_t getCharWidth(const nbgl_font_t *font, uint32_t unicode, bool is_unicode) { - if (is_unicode) { +static uint8_t getCharWidth(const nbgl_font_t *font, uint32_t unicode, bool is_unicode) +{ + if (is_unicode) { #ifdef HAVE_UNICODE_SUPPORT - const nbgl_font_unicode_character_t *unicodeCharacter = nbgl_getUnicodeFontCharacter(unicode); - if (!unicodeCharacter) { - return 0; + const nbgl_font_unicode_character_t *unicodeCharacter + = nbgl_getUnicodeFontCharacter(unicode); + if (!unicodeCharacter) { + return 0; + } + return unicodeCharacter->width; +#else // HAVE_UNICODE_SUPPORT + return 0; +#endif // HAVE_UNICODE_SUPPORT } - return unicodeCharacter->width; -#else // HAVE_UNICODE_SUPPORT - return 0; -#endif // HAVE_UNICODE_SUPPORT - } - else { - const nbgl_font_character_t *character; // non-unicode char - if ((unicode < font->first_char) || (unicode > font->last_char)) { - return 0; + else { + const nbgl_font_character_t *character; // non-unicode char + if ((unicode < font->first_char) || (unicode > font->last_char)) { + return 0; + } + character + = (const nbgl_font_character_t *) PIC(&font->characters[unicode - font->first_char]); + return character->width; } - character = (const nbgl_font_character_t *)PIC(&font->characters[unicode-font->first_char]); - return character->width; - } } /** - * @brief return the max width in pixels of the given text until the first terminator (\n if breakOnLineEnd, or \0) is encountered, - * or maxLen bytes have been parsed. + * @brief return the max width in pixels of the given text until the first terminator (\n if + * breakOnLineEnd, or \0) is encountered, or maxLen bytes have been parsed. * * @param fontId font ID * @param text text in UTF8 @@ -205,40 +212,45 @@ static uint8_t getCharWidth(const nbgl_font_t *font, uint32_t unicode, bool is_u * @param maxLen max number of bytes to parse in text * @return the width in pixels of the text */ -static uint16_t getTextWidth(nbgl_font_id_e fontId, const char* text, bool breakOnLineEnd, uint16_t maxLen) { - uint16_t line_width=0; - uint16_t max_width=0; - const nbgl_font_t *font = nbgl_getFont(fontId); - uint16_t textLen = MIN(strlen(text), maxLen); +static uint16_t getTextWidth(nbgl_font_id_e fontId, + const char *text, + bool breakOnLineEnd, + uint16_t maxLen) +{ + uint16_t line_width = 0; + uint16_t max_width = 0; + const nbgl_font_t *font = nbgl_getFont(fontId); + uint16_t textLen = MIN(strlen(text), maxLen); #ifdef HAVE_UNICODE_SUPPORT - nbgl_getUnicodeFont(fontId); -#endif // HAVE_UNICODE_SUPPORT - // end loop text len is NULL (max reached) - while (textLen) { - uint8_t char_width; - uint32_t unicode; - bool is_unicode; - - unicode = nbgl_popUnicodeChar((const uint8_t **)&text, &textLen, &is_unicode); - - if (unicode == '\n') { - if (breakOnLineEnd) - break; - // reset line width for next line - line_width=0; - continue; - } + nbgl_getUnicodeFont(fontId); +#endif // HAVE_UNICODE_SUPPORT + // end loop text len is NULL (max reached) + while (textLen) { + uint8_t char_width; + uint32_t unicode; + bool is_unicode; + + unicode = nbgl_popUnicodeChar((const uint8_t **) &text, &textLen, &is_unicode); + + if (unicode == '\n') { + if (breakOnLineEnd) { + break; + } + // reset line width for next line + line_width = 0; + continue; + } - char_width = getCharWidth(font, unicode, is_unicode); + char_width = getCharWidth(font, unicode, is_unicode); - line_width += char_width; - // memorize max line width if greater than current - if (line_width>max_width) { - max_width = line_width; + line_width += char_width; + // memorize max line width if greater than current + if (line_width > max_width) { + max_width = line_width; + } } - } - return max_width; + return max_width; } /** @@ -248,8 +260,9 @@ static uint16_t getTextWidth(nbgl_font_id_e fontId, const char* text, bool break * @param text text in UTF8 * @return the width in pixels of the text */ -uint16_t nbgl_getSingleLineTextWidth(nbgl_font_id_e fontId, const char* text) { - return getTextWidth(fontId, text, true, 0xFFFF); +uint16_t nbgl_getSingleLineTextWidth(nbgl_font_id_e fontId, const char *text) +{ + return getTextWidth(fontId, text, true, 0xFFFF); } /** @@ -260,8 +273,9 @@ uint16_t nbgl_getSingleLineTextWidth(nbgl_font_id_e fontId, const char* text) { * @param text text in UTF8 * @return the width in pixels of the text */ -uint16_t nbgl_getSingleLineTextWidthInLen(nbgl_font_id_e fontId, const char* text, uint16_t maxLen) { - return getTextWidth(fontId, text, true, maxLen); +uint16_t nbgl_getSingleLineTextWidthInLen(nbgl_font_id_e fontId, const char *text, uint16_t maxLen) +{ + return getTextWidth(fontId, text, true, maxLen); } /** @@ -271,8 +285,9 @@ uint16_t nbgl_getSingleLineTextWidthInLen(nbgl_font_id_e fontId, const char* tex * @param text text in UTF8 * @return the width in pixels of the text */ -uint16_t nbgl_getTextWidth(nbgl_font_id_e fontId, const char* text) { - return getTextWidth(fontId, text, false, 0xFFFF); +uint16_t nbgl_getTextWidth(nbgl_font_id_e fontId, const char *text) +{ + return getTextWidth(fontId, text, false, 0xFFFF); } /** @@ -282,19 +297,20 @@ uint16_t nbgl_getTextWidth(nbgl_font_id_e fontId, const char* text) { * @param text UTF-8 character * @return the width in pixels of the character */ -uint8_t nbgl_getCharWidth(nbgl_font_id_e fontId, const char *text) { - const nbgl_font_t *font = nbgl_getFont(fontId); - uint32_t unicode; - bool is_unicode; - uint16_t textLen=4; // max len for a char +uint8_t nbgl_getCharWidth(nbgl_font_id_e fontId, const char *text) +{ + const nbgl_font_t *font = nbgl_getFont(fontId); + uint32_t unicode; + bool is_unicode; + uint16_t textLen = 4; // max len for a char #ifdef HAVE_UNICODE_SUPPORT - nbgl_getUnicodeFont(fontId); -#endif // HAVE_UNICODE_SUPPORT + nbgl_getUnicodeFont(fontId); +#endif // HAVE_UNICODE_SUPPORT - unicode = nbgl_popUnicodeChar((const uint8_t**)&text, &textLen, &is_unicode); + unicode = nbgl_popUnicodeChar((const uint8_t **) &text, &textLen, &is_unicode); - return getCharWidth(font, unicode, is_unicode); + return getCharWidth(font, unicode, is_unicode); } /** @@ -303,9 +319,10 @@ uint8_t nbgl_getCharWidth(nbgl_font_id_e fontId, const char *text) { * @param fontId font ID * @return the height in pixels */ -uint8_t nbgl_getFontHeight(nbgl_font_id_e fontId) { - const nbgl_font_t *font = nbgl_getFont(fontId); - return font->height; +uint8_t nbgl_getFontHeight(nbgl_font_id_e fontId) +{ + const nbgl_font_t *font = nbgl_getFont(fontId); + return font->height; } /** @@ -314,9 +331,10 @@ uint8_t nbgl_getFontHeight(nbgl_font_id_e fontId) { * @param fontId font ID * @return the height in pixels */ -uint8_t nbgl_getFontLineHeight(nbgl_font_id_e fontId) { - const nbgl_font_t *font = nbgl_getFont(fontId); - return font->line_height; +uint8_t nbgl_getFontLineHeight(nbgl_font_id_e fontId) +{ + const nbgl_font_t *font = nbgl_getFont(fontId); + return font->line_height; } /** @@ -325,15 +343,16 @@ uint8_t nbgl_getFontLineHeight(nbgl_font_id_e fontId) { * @param text text to get the number of lines from * @return the number of lines in the given text */ -uint16_t nbgl_getTextNbLines(const char*text) { - uint16_t nbLines = 1; - while (*text) { - if (*text == '\n') { - nbLines++; +uint16_t nbgl_getTextNbLines(const char *text) +{ + uint16_t nbLines = 1; + while (*text) { + if (*text == '\n') { + nbLines++; + } + text++; } - text++; - } - return nbLines; + return nbLines; } /** @@ -343,9 +362,10 @@ uint16_t nbgl_getTextNbLines(const char*text) { * @param text text to get the height from * @return the height in pixels */ -uint16_t nbgl_getTextHeight(nbgl_font_id_e fontId, const char*text) { - const nbgl_font_t *font = nbgl_getFont(fontId); - return (nbgl_getTextNbLines(text)*font->line_height); +uint16_t nbgl_getTextHeight(nbgl_font_id_e fontId, const char *text) +{ + const nbgl_font_t *font = nbgl_getFont(fontId); + return (nbgl_getTextNbLines(text) * font->line_height); } /** @@ -355,12 +375,13 @@ uint16_t nbgl_getTextHeight(nbgl_font_id_e fontId, const char*text) { * @param text text to get the number of bytes from * @return the number of bytes in the given text */ -uint16_t nbgl_getTextLength(const char* text) { - const char* origText = text; - while ((*text) && (*text != '\n')) { - text++; - } - return text-origText; +uint16_t nbgl_getTextLength(const char *text) +{ + const char *origText = text; + while ((*text) && (*text != '\n')) { + text++; + } + return text - origText; } /** @@ -375,54 +396,61 @@ uint16_t nbgl_getTextLength(const char* text) { * @return true if maxWidth is reached, false otherwise * */ -void nbgl_getTextMaxLenAndWidth(nbgl_font_id_e fontId, const char* text, uint16_t maxWidth, uint16_t *len, uint16_t *width, bool wrapping) { - const nbgl_font_t *font = nbgl_getFont(fontId); - uint16_t textLen = nbgl_getTextLength(text); - uint32_t lenAtLastDelimiter = 0, widthAtlastDelimiter = 0; +void nbgl_getTextMaxLenAndWidth(nbgl_font_id_e fontId, + const char *text, + uint16_t maxWidth, + uint16_t *len, + uint16_t *width, + bool wrapping) +{ + const nbgl_font_t *font = nbgl_getFont(fontId); + uint16_t textLen = nbgl_getTextLength(text); + uint32_t lenAtLastDelimiter = 0, widthAtlastDelimiter = 0; #ifdef HAVE_UNICODE_SUPPORT - nbgl_getUnicodeFont(fontId); -#endif // HAVE_UNICODE_SUPPORT - - *width=0; - *len=0; - while (textLen) { - uint8_t char_width; - uint32_t unicode; - bool is_unicode; - uint16_t curTextLen = textLen; - - unicode = nbgl_popUnicodeChar((const uint8_t **)&text, &textLen, &is_unicode); - // if \n, exit - if (unicode == '\n') { - *len += curTextLen-textLen; - return; - } + nbgl_getUnicodeFont(fontId); +#endif // HAVE_UNICODE_SUPPORT + + *width = 0; + *len = 0; + while (textLen) { + uint8_t char_width; + uint32_t unicode; + bool is_unicode; + uint16_t curTextLen = textLen; + + unicode = nbgl_popUnicodeChar((const uint8_t **) &text, &textLen, &is_unicode); + // if \n, exit + if (unicode == '\n') { + *len += curTextLen - textLen; + return; + } - char_width = getCharWidth(font, unicode, is_unicode); - if (char_width == 0) - continue; + char_width = getCharWidth(font, unicode, is_unicode); + if (char_width == 0) { + continue; + } - // memorize cursors at last found sepator, when wrapping - if ((wrapping == true) && IS_WORD_DELIM(unicode)) { - lenAtLastDelimiter = *len; - widthAtlastDelimiter = *width; - } - if ((*width+char_width) > maxWidth) { - if ((wrapping == true) && (widthAtlastDelimiter > 0)) { - *len = lenAtLastDelimiter+1; - *width = widthAtlastDelimiter; - } - return; + // memorize cursors at last found sepator, when wrapping + if ((wrapping == true) && IS_WORD_DELIM(unicode)) { + lenAtLastDelimiter = *len; + widthAtlastDelimiter = *width; + } + if ((*width + char_width) > maxWidth) { + if ((wrapping == true) && (widthAtlastDelimiter > 0)) { + *len = lenAtLastDelimiter + 1; + *width = widthAtlastDelimiter; + } + return; + } + *len += curTextLen - textLen; + *width = *width + char_width; } - *len += curTextLen-textLen; - *width = *width+char_width; - } } - /** - * @brief compute the len of the given text (in bytes) fitting in the given maximum nb lines, with the given maximum width + * @brief compute the len of the given text (in bytes) fitting in the given maximum nb lines, with + * the given maximum width * * @param fontId font ID * @param text input UTF-8 string, possibly multi-line @@ -433,49 +461,56 @@ void nbgl_getTextMaxLenAndWidth(nbgl_font_id_e fontId, const char* text, uint16_ * @return true if maxNbLines is reached, false otherwise * */ -bool nbgl_getTextMaxLenInNbLines(nbgl_font_id_e fontId, const char* text, uint16_t maxWidth, uint16_t maxNbLines, uint16_t *len) { - const nbgl_font_t *font = nbgl_getFont(fontId); - uint16_t textLen = strlen(text); - uint16_t width = 0; - const char *origText = text; +bool nbgl_getTextMaxLenInNbLines(nbgl_font_id_e fontId, + const char *text, + uint16_t maxWidth, + uint16_t maxNbLines, + uint16_t *len) +{ + const nbgl_font_t *font = nbgl_getFont(fontId); + uint16_t textLen = strlen(text); + uint16_t width = 0; + const char *origText = text; #ifdef HAVE_UNICODE_SUPPORT - nbgl_getUnicodeFont(fontId); -#endif // HAVE_UNICODE_SUPPORT - - while ((textLen)&&(maxNbLines>0)) { - uint8_t char_width; - uint32_t unicode; - bool is_unicode; - - unicode = nbgl_popUnicodeChar((const uint8_t **)&text, &textLen, &is_unicode); - // if \n, reset width - if (unicode == '\n') { - maxNbLines--; - width = 0; - continue; - } + nbgl_getUnicodeFont(fontId); +#endif // HAVE_UNICODE_SUPPORT + + while ((textLen) && (maxNbLines > 0)) { + uint8_t char_width; + uint32_t unicode; + bool is_unicode; + + unicode = nbgl_popUnicodeChar((const uint8_t **) &text, &textLen, &is_unicode); + // if \n, reset width + if (unicode == '\n') { + maxNbLines--; + width = 0; + continue; + } + + char_width = getCharWidth(font, unicode, is_unicode); + if (char_width == 0) { + continue; + } - char_width = getCharWidth(font, unicode, is_unicode); - if (char_width == 0) - continue; - - if ((width+char_width) > maxWidth) { - width = 0; - maxNbLines--; - if (maxNbLines == 0) { - break; - } - continue; + if ((width + char_width) > maxWidth) { + width = 0; + maxNbLines--; + if (maxNbLines == 0) { + break; + } + continue; + } + width += char_width; } - width += char_width; - } - *len = text-origText; - return (maxNbLines == 0); + *len = text - origText; + return (maxNbLines == 0); } /** - * @brief compute the len and width of the given text fitting in the maxWidth, starting from end of text + * @brief compute the len and width of the given text fitting in the maxWidth, starting from end of + * text * @note works only with ASCII string * * @param fontId font ID @@ -487,39 +522,45 @@ bool nbgl_getTextMaxLenInNbLines(nbgl_font_id_e fontId, const char* text, uint16 * @return true if maxWidth is reached, false otherwise * */ -bool nbgl_getTextMaxLenAndWidthFromEnd(nbgl_font_id_e fontId, const char* text, uint16_t maxWidth, uint16_t *len, uint16_t *width) { - const nbgl_font_t *font = nbgl_getFont(fontId); - uint16_t textLen = nbgl_getTextLength(text); - - *width=0; - *len=0; - while (textLen) { - const nbgl_font_character_t *character; - uint8_t char_width; - char cur_char; - - textLen--; - cur_char = text[textLen]; - // if \n, exit - if (cur_char == '\n') { - *len = *len +1; - continue; - } +bool nbgl_getTextMaxLenAndWidthFromEnd(nbgl_font_id_e fontId, + const char *text, + uint16_t maxWidth, + uint16_t *len, + uint16_t *width) +{ + const nbgl_font_t *font = nbgl_getFont(fontId); + uint16_t textLen = nbgl_getTextLength(text); + + *width = 0; + *len = 0; + while (textLen) { + const nbgl_font_character_t *character; + uint8_t char_width; + char cur_char; + + textLen--; + cur_char = text[textLen]; + // if \n, exit + if (cur_char == '\n') { + *len = *len + 1; + continue; + } - // skip not printable char - if ((cur_char < font->first_char) || (cur_char > font->last_char)) { - continue; - } - character = (const nbgl_font_character_t *)PIC(&font->characters[cur_char-font->first_char]); - char_width = character->width; + // skip not printable char + if ((cur_char < font->first_char) || (cur_char > font->last_char)) { + continue; + } + character + = (const nbgl_font_character_t *) PIC(&font->characters[cur_char - font->first_char]); + char_width = character->width; - if ((*width+char_width) > maxWidth) { - return true; + if ((*width + char_width) > maxWidth) { + return true; + } + *len = *len + 1; + *width = *width + char_width; } - *len = *len +1; - *width = *width+char_width; - } - return false; + return false; } /** @@ -531,63 +572,68 @@ bool nbgl_getTextMaxLenAndWidthFromEnd(nbgl_font_id_e fontId, const char* text, * @param wrapping if true, lines are split on separators like spaces, \n... * @return the number of lines in the given text */ -uint16_t nbgl_getTextNbLinesInWidth(nbgl_font_id_e fontId, const char* text, uint16_t maxWidth, bool wrapping) { - const nbgl_font_t *font = nbgl_getFont(fontId); - uint16_t width=0; - uint16_t nbLines=1; - uint16_t textLen = strlen(text); - const char *lastDelimiter = NULL; - uint32_t lenAtLastDelimiter = 0; - const char *prevText = NULL; +uint16_t nbgl_getTextNbLinesInWidth(nbgl_font_id_e fontId, + const char *text, + uint16_t maxWidth, + bool wrapping) +{ + const nbgl_font_t *font = nbgl_getFont(fontId); + uint16_t width = 0; + uint16_t nbLines = 1; + uint16_t textLen = strlen(text); + const char *lastDelimiter = NULL; + uint32_t lenAtLastDelimiter = 0; + const char *prevText = NULL; #ifdef HAVE_UNICODE_SUPPORT - nbgl_getUnicodeFont(fontId); -#endif // HAVE_UNICODE_SUPPORT - // end loop when a '\0' is uncountered - while (textLen) { - uint8_t char_width; - uint32_t unicode; - bool is_unicode; - - // memorize the last char - prevText = text; - unicode = nbgl_popUnicodeChar((const uint8_t **)&text, &textLen, &is_unicode); - - // memorize cursors at last found space - if ((wrapping == true) && (IS_WORD_DELIM(unicode))) { - lastDelimiter = prevText; - lenAtLastDelimiter = textLen; - } - // if \n, increment the number of lines - if (unicode == '\n') { - nbLines++; - width = 0; - lastDelimiter = NULL; - continue; - } + nbgl_getUnicodeFont(fontId); +#endif // HAVE_UNICODE_SUPPORT + // end loop when a '\0' is uncountered + while (textLen) { + uint8_t char_width; + uint32_t unicode; + bool is_unicode; + + // memorize the last char + prevText = text; + unicode = nbgl_popUnicodeChar((const uint8_t **) &text, &textLen, &is_unicode); + + // memorize cursors at last found space + if ((wrapping == true) && (IS_WORD_DELIM(unicode))) { + lastDelimiter = prevText; + lenAtLastDelimiter = textLen; + } + // if \n, increment the number of lines + if (unicode == '\n') { + nbLines++; + width = 0; + lastDelimiter = NULL; + continue; + } - char_width = getCharWidth(font, unicode, is_unicode); - if (char_width == 0) - continue; - - // if about to reach max len, increment the number of lines - if ((width+char_width)>maxWidth) { - if ((wrapping == true) && (lastDelimiter != NULL)) { - text = lastDelimiter+1; - lastDelimiter = NULL; - textLen = lenAtLastDelimiter; - width = 0; - } - else { - width = char_width; - } - nbLines++; - } - else { - width += char_width; + char_width = getCharWidth(font, unicode, is_unicode); + if (char_width == 0) { + continue; + } + + // if about to reach max len, increment the number of lines + if ((width + char_width) > maxWidth) { + if ((wrapping == true) && (lastDelimiter != NULL)) { + text = lastDelimiter + 1; + lastDelimiter = NULL; + textLen = lenAtLastDelimiter; + width = 0; + } + else { + width = char_width; + } + nbLines++; + } + else { + width += char_width; + } } - } - return nbLines; + return nbLines; } /** @@ -598,93 +644,101 @@ uint16_t nbgl_getTextNbLinesInWidth(nbgl_font_id_e fontId, const char* text, uin * @param maxWidth maximum width in which the text must fit * @return the height in pixels */ -uint16_t nbgl_getTextHeightInWidth(nbgl_font_id_e fontId, const char*text, uint16_t maxWidth, bool wrapping) { - const nbgl_font_t *font = nbgl_getFont(fontId); - return (nbgl_getTextNbLinesInWidth(fontId,text,maxWidth,wrapping)*font->line_height); +uint16_t nbgl_getTextHeightInWidth(nbgl_font_id_e fontId, + const char *text, + uint16_t maxWidth, + bool wrapping) +{ + const nbgl_font_t *font = nbgl_getFont(fontId); + return (nbgl_getTextNbLinesInWidth(fontId, text, maxWidth, wrapping) * font->line_height); } /** - * @brief Modifies the given text to wrap it on the given max width (in pixels), in the given nbLines - * If possible, + * @brief Modifies the given text to wrap it on the given max width (in pixels), in the given + * nbLines If possible, * * @param fontId font ID * @param text (input/output) UTF-8 string, possibly multi-line * @param maxWidth maximum width in pixels - * @param nbLines (input) If the text doesn't fit in this number of lines, the last chars will be replaced by ... + * @param nbLines (input) If the text doesn't fit in this number of lines, the last chars will be + * replaced by ... * */ -void nbgl_textWrapOnNbLines(nbgl_font_id_e fontId, char* text, uint16_t maxWidth, uint8_t nbLines) { - const nbgl_font_t *font = nbgl_getFont(fontId); - uint16_t textLen = nbgl_getTextLength(text); - uint16_t width = 0; - uint8_t currentNbLines = 1; - char *lastDelimiter = NULL; - uint32_t lenAtLastDelimiter = 0; - char *prevText = NULL; +void nbgl_textWrapOnNbLines(nbgl_font_id_e fontId, char *text, uint16_t maxWidth, uint8_t nbLines) +{ + const nbgl_font_t *font = nbgl_getFont(fontId); + uint16_t textLen = nbgl_getTextLength(text); + uint16_t width = 0; + uint8_t currentNbLines = 1; + char *lastDelimiter = NULL; + uint32_t lenAtLastDelimiter = 0; + char *prevText = NULL; #ifdef HAVE_UNICODE_SUPPORT - nbgl_getUnicodeFont(fontId); + nbgl_getUnicodeFont(fontId); #endif - while (*text) { - uint8_t char_width; - uint32_t unicode; - bool is_unicode; - char *prevPrevText; - - // memorize the two last chars - prevPrevText = prevText; - prevText = text; - unicode = nbgl_popUnicodeChar((const uint8_t **)&text, &textLen, &is_unicode); - // if \n, reset width - if (unicode == '\n') { - width = 0; - currentNbLines++; - lastDelimiter = NULL; - continue; - } - - char_width = getCharWidth(font, unicode, is_unicode); - if (char_width == 0) - continue; + while (*text) { + uint8_t char_width; + uint32_t unicode; + bool is_unicode; + char *prevPrevText; + + // memorize the two last chars + prevPrevText = prevText; + prevText = text; + unicode = nbgl_popUnicodeChar((const uint8_t **) &text, &textLen, &is_unicode); + // if \n, reset width + if (unicode == '\n') { + width = 0; + currentNbLines++; + lastDelimiter = NULL; + continue; + } - // memorize cursors at last found space - if (IS_WORD_DELIM(unicode)) { - lastDelimiter = prevText; - lenAtLastDelimiter = textLen+1; - } - // if the width is about to overpass maxWidth, do something - if ((width+char_width) > maxWidth) { - // if the max number of lines has not been reached, try to wrap on last space encountered - if (currentNbLines maxWidth) { + // if the max number of lines has not been reached, try to wrap on last space + // encountered + if (currentNbLines < nbLines) { + currentNbLines++; + // replace last found space by a \n + if (lastDelimiter != NULL) { + *lastDelimiter++ = '\n'; + text = lastDelimiter; + lastDelimiter = NULL; + textLen = lenAtLastDelimiter; + } + else { + textLen += text - prevText; + text = prevText; + } + // reset width for next line + width = 0; + } + else { + // replace the 2 last chars by '...' (should be same width) + if (prevPrevText != NULL) { + *prevPrevText++ = '.'; + *prevPrevText++ = '.'; + *prevPrevText++ = '.'; + *prevPrevText = '\0'; + } + return; + } } - return; - } + width += char_width; } - width += char_width; - } } #ifdef HAVE_UNICODE_SUPPORT @@ -695,72 +749,77 @@ void nbgl_textWrapOnNbLines(nbgl_font_id_e fontId, char* text, uint16_t maxWidth * @return the found unicode context structure or NULL if not found */ -nbgl_unicode_ctx_t* nbgl_getUnicodeFont(nbgl_font_id_e fontId) { - if ((unicodeCtx.font != NULL) && (unicodeCtx.font->font_id == fontId)) { - return &unicodeCtx; - } +nbgl_unicode_ctx_t *nbgl_getUnicodeFont(nbgl_font_id_e fontId) +{ + if ((unicodeCtx.font != NULL) && (unicodeCtx.font->font_id == fontId)) { + return &unicodeCtx; + } #if defined(HAVE_LANGUAGE_PACK) - // Be sure we need to change font - const uint8_t *ptr = (const uint8_t *)language_pack; - const nbgl_font_unicode_t *font = (const void *)(ptr + language_pack->fonts_offset); - unicodeCtx.characters = (const nbgl_font_unicode_character_t *)(ptr + language_pack->characters_offset); - unicodeCtx.bitmap = (const uint8_t *)(ptr + language_pack->bitmaps_offset); - - for (uint32_t i=0; i < language_pack->nb_fonts; i++) { - if (font->font_id == fontId) { - // Update all other global variables - unicodeCtx.font = font; - return &unicodeCtx; + // Be sure we need to change font + const uint8_t *ptr = (const uint8_t *) language_pack; + const nbgl_font_unicode_t *font = (const void *) (ptr + language_pack->fonts_offset); + unicodeCtx.characters + = (const nbgl_font_unicode_character_t *) (ptr + language_pack->characters_offset); + unicodeCtx.bitmap = (const uint8_t *) (ptr + language_pack->bitmaps_offset); + + for (uint32_t i = 0; i < language_pack->nb_fonts; i++) { + if (font->font_id == fontId) { + // Update all other global variables + unicodeCtx.font = font; + return &unicodeCtx; + } + // Compute next Bitmap offset + unicodeCtx.bitmap += font->bitmap_len; + + // Update all pointers for next font + unicodeCtx.characters += language_pack->nb_characters; + font++; } - // Compute next Bitmap offset - unicodeCtx.bitmap += font->bitmap_len; - - // Update all pointers for next font - unicodeCtx.characters += language_pack->nb_characters; - font++; - } -#endif //defined(HAVE_LANGUAGE_PACK) - // id not found - return NULL; +#endif // defined(HAVE_LANGUAGE_PACK) + // id not found + return NULL; } /** - * @brief Get the unicode character object matching the given unicode (a unicode character is encoded on max of 3 chars) + * @brief Get the unicode character object matching the given unicode (a unicode character is + encoded on max of 3 chars) * in the current language * * @param unicode the unicode value of the character * @return the found character or NULL if not found */ -const nbgl_font_unicode_character_t *nbgl_getUnicodeFontCharacter(uint32_t unicode) { +const nbgl_font_unicode_character_t *nbgl_getUnicodeFontCharacter(uint32_t unicode) +{ #if defined(HAVE_LANGUAGE_PACK) - const nbgl_font_unicode_character_t *characters = (const nbgl_font_unicode_character_t *)PIC(unicodeCtx.characters); - uint32_t n = language_pack->nb_characters; - if (characters == NULL) { - return NULL; - } - // For the moment, let just parse the full array, but at the end let use - // binary search as data are sorted by unicode value ! - for (unsigned i=0; i < n-1; i++, characters++) { - if (characters->char_unicode == unicode) { - // Compute & store the number of bytes used to display this character - unicodeCtx.unicode_character_byte_count = \ - (characters+1)->bitmap_offset - characters->bitmap_offset; - return characters; + const nbgl_font_unicode_character_t *characters + = (const nbgl_font_unicode_character_t *) PIC(unicodeCtx.characters); + uint32_t n = language_pack->nb_characters; + if (characters == NULL) { + return NULL; } - } - // By default, let's use the last Unicode character, which should be the - // 0x00FFFD one, used to replace unrecognized or unrepresentable character. - - // Compute & store the number of bytes used to display this character - unicodeCtx.unicode_character_byte_count = unicodeCtx.font->bitmap_len - \ - characters->bitmap_offset; - return characters; -#else //defined(HAVE_LANGUAGE_PACK) - UNUSED(unicode); - // id not found - return NULL; -#endif //defined(HAVE_LANGUAGE_PACK) + // For the moment, let just parse the full array, but at the end let use + // binary search as data are sorted by unicode value ! + for (unsigned i = 0; i < n - 1; i++, characters++) { + if (characters->char_unicode == unicode) { + // Compute & store the number of bytes used to display this character + unicodeCtx.unicode_character_byte_count + = (characters + 1)->bitmap_offset - characters->bitmap_offset; + return characters; + } + } + // By default, let's use the last Unicode character, which should be the + // 0x00FFFD one, used to replace unrecognized or unrepresentable character. + + // Compute & store the number of bytes used to display this character + unicodeCtx.unicode_character_byte_count + = unicodeCtx.font->bitmap_len - characters->bitmap_offset; + return characters; +#else // defined(HAVE_LANGUAGE_PACK) + UNUSED(unicode); + // id not found + return NULL; +#endif // defined(HAVE_LANGUAGE_PACK) } /** @@ -769,24 +828,27 @@ const nbgl_font_unicode_character_t *nbgl_getUnicodeFontCharacter(uint32_t unico * * @return bitmap byte count of that character (0 for empty ones, ie space) */ -uint32_t nbgl_getUnicodeFontCharacterByteCount(void) { +uint32_t nbgl_getUnicodeFontCharacterByteCount(void) +{ #ifdef HAVE_LANGUAGE_PACK - return unicodeCtx.unicode_character_byte_count; -#else //defined(HAVE_LANGUAGE_PACK) - return 0; -#endif // HAVE_LANGUAGE_PACK + return unicodeCtx.unicode_character_byte_count; +#else // defined(HAVE_LANGUAGE_PACK) + return 0; +#endif // HAVE_LANGUAGE_PACK } #ifdef HAVE_LANGUAGE_PACK /** * @brief Function to be called when a change on the current language pack is notified by the OS, - * to be sure that the current unicodeCtx variable will be set again at next @ref nbgl_getUnicodeFont() call + * to be sure that the current unicodeCtx variable will be set again at next @ref + * nbgl_getUnicodeFont() call * */ -void nbgl_refreshUnicodeFont(void) { - unicodeCtx.font = NULL; - unicodeCtx.characters = NULL; +void nbgl_refreshUnicodeFont(void) +{ + unicodeCtx.font = NULL; + unicodeCtx.characters = NULL; } -#endif // HAVE_LANGUAGE_PACK +#endif // HAVE_LANGUAGE_PACK -#endif // HAVE_UNICODE_SUPPORT +#endif // HAVE_UNICODE_SUPPORT diff --git a/lib_nbgl/src/nbgl_layout.c b/lib_nbgl/src/nbgl_layout.c index bf2f53ff4..0ff49ddc9 100644 --- a/lib_nbgl/src/nbgl_layout.c +++ b/lib_nbgl/src/nbgl_layout.c @@ -23,11 +23,11 @@ * DEFINES *********************/ // half internal margin, between items -#define INTERNAL_SPACE 16 +#define INTERNAL_SPACE 16 // internal margin, between sub-items #define INTERNAL_MARGIN 8 // inner margin, between buttons -#define INNER_MARGIN 12 +#define INNER_MARGIN 12 #define NB_MAX_LAYOUTS 3 @@ -46,7 +46,7 @@ #define TAG_VALUE_ICON_WIDTH 32 #define TOUCHABLE_BAR_HEIGHT 88 -#define FOOTER_HEIGHT 80 +#define FOOTER_HEIGHT 80 // refresh period of the spinner, in ms #define SPINNER_REFRESH_PERIOD 400 @@ -54,21 +54,23 @@ /********************** * MACROS **********************/ -#define ASSERT_ENOUGH_PLACE_FOR_MAIN_PANEL_CHILD(__layout) { \ - if ((__layout)->panel.nbChildren==(NB_MAX_MAIN_PANEL_CHILDREN-1)) return NO_MORE_OBJ_ERROR; \ -} +#define ASSERT_ENOUGH_PLACE_FOR_MAIN_PANEL_CHILD(__layout) \ + { \ + if ((__layout)->panel.nbChildren == (NB_MAX_MAIN_PANEL_CHILDREN - 1)) \ + return NO_MORE_OBJ_ERROR; \ + } -#define AVAILABLE_WIDTH (SCREEN_WIDTH-(2*BORDER_MARGIN)) +#define AVAILABLE_WIDTH (SCREEN_WIDTH - (2 * BORDER_MARGIN)) /********************** * TYPEDEFS **********************/ typedef struct { - nbgl_obj_t* obj; - uint8_t token; // user token, attached to callback - uint8_t index; // index within the token - tune_index_e tuneId; // if not @ref NBGL_NO_TUNE, a tune will be played + nbgl_obj_t *obj; + uint8_t token; // user token, attached to callback + uint8_t index; // index within the token + tune_index_e tuneId; // if not @ref NBGL_NO_TUNE, a tune will be played } layoutObj_t; /** @@ -77,24 +79,26 @@ typedef struct { * */ typedef struct nbgl_layoutInternal_s { - bool modal; ///< if true, means the screen is a modal - bool withLeftBorder; ///< if true, draws a light gray left border on the whole height of the screen - uint8_t layer; ///< if >0, puts the layout on top of screen stack (modal). Otherwise puts on background (for apps) - uint8_t nbChildren; ///< number of children in above array - nbgl_obj_t **children; ///< children for main screen - - nbgl_obj_type_t bottomContainerUsage; - uint8_t nbPages; ///< number of pages for navigation bar - uint8_t activePage; ///< index of active page for navigation bar - nbgl_container_t *bottomContainer; // Used for navigation bar - nbgl_text_area_t *tapText; - nbgl_layoutTouchCallback_t callback; // user callback for all controls - // This is the pool of callback objects, potentially used by this layout - layoutObj_t callbackObjPool[LAYOUT_OBJ_POOL_LEN]; - // number of callback objects used by the whole layout in callbackObjPool - uint8_t nbUsedCallbackObjs; - - nbgl_container_t *container; + bool modal; ///< if true, means the screen is a modal + bool withLeftBorder; ///< if true, draws a light gray left border on the whole height of the + ///< screen + uint8_t layer; ///< if >0, puts the layout on top of screen stack (modal). Otherwise puts on + ///< background (for apps) + uint8_t nbChildren; ///< number of children in above array + nbgl_obj_t **children; ///< children for main screen + + nbgl_obj_type_t bottomContainerUsage; + uint8_t nbPages; ///< number of pages for navigation bar + uint8_t activePage; ///< index of active page for navigation bar + nbgl_container_t *bottomContainer; // Used for navigation bar + nbgl_text_area_t *tapText; + nbgl_layoutTouchCallback_t callback; // user callback for all controls + // This is the pool of callback objects, potentially used by this layout + layoutObj_t callbackObjPool[LAYOUT_OBJ_POOL_LEN]; + // number of callback objects used by the whole layout in callbackObjPool + uint8_t nbUsedCallbackObjs; + + nbgl_container_t *container; } nbgl_layoutInternal_t; @@ -110,7 +114,7 @@ static nbgl_layoutInternal_t gLayout[NB_MAX_LAYOUTS] = {0}; #ifdef NBGL_KEYBOARD static nbgl_button_t *choiceButtons[NB_MAX_SUGGESTION_BUTTONS]; -#endif // NBGL_KEYBOARD +#endif // NBGL_KEYBOARD #ifdef NBGL_KEYBOARD static char numText[5]; @@ -122,289 +126,336 @@ static char numText[5]; #ifdef HAVE_DISPLAY_FAST_MODE // Unit step in % of touchable progress bar -#define HOLD_TO_APPROVE_STEP_PERCENT (10) +#define HOLD_TO_APPROVE_STEP_PERCENT (10) // Duration in ms the user must hold the progress bar // to make it progress HOLD_TO_APPROVE_STEP_PERCENT %. // This duration must be higher than the screen refresh duration. #define HOLD_TO_APPROVE_STEP_DURATION_MS (150) #else -#define HOLD_TO_APPROVE_STEP_PERCENT (17) +#define HOLD_TO_APPROVE_STEP_PERCENT (17) #define HOLD_TO_APPROVE_STEP_DURATION_MS (400) -#endif // HAVE_DISPLAY_FAST_MODE +#endif // HAVE_DISPLAY_FAST_MODE -static inline uint8_t get_hold_to_approve_percent(uint32_t touch_duration) { - uint8_t current_step_nb = (touch_duration / HOLD_TO_APPROVE_STEP_DURATION_MS) + 1; - return (current_step_nb * HOLD_TO_APPROVE_STEP_PERCENT); +static inline uint8_t get_hold_to_approve_percent(uint32_t touch_duration) +{ + uint8_t current_step_nb = (touch_duration / HOLD_TO_APPROVE_STEP_DURATION_MS) + 1; + return (current_step_nb * HOLD_TO_APPROVE_STEP_PERCENT); } // function used to retrieve the concerned layout and layout obj matching the given touched obj -static bool getLayoutAndLayoutObj(nbgl_obj_t *obj, nbgl_layoutInternal_t **layout, layoutObj_t **layoutObj) { - uint8_t i = NB_MAX_LAYOUTS; - - // parse all layouts (starting with modals) to find the object - *layout = NULL; - while (i>0) { - i--; - if (gLayout[i].nbChildren > 0) { - uint8_t j; - - // search index of obj in this layout - for (j=0;j 0) { + i--; + if (gLayout[i].nbChildren > 0) { + uint8_t j; + + // search index of obj in this layout + for (j = 0; j < gLayout[i].nbUsedCallbackObjs; j++) { + if (obj == gLayout[i].callbackObjPool[j].obj) { + LOG_DEBUG(LAYOUT_LOGGER, + "getLayoutAndLayoutObj(): obj found in layout[%d], index = %d, " + "nbUsedCallbackObjs = %d\n", + i, + j, + gLayout[i].nbUsedCallbackObjs); + *layout = &gLayout[i]; + *layoutObj = &(gLayout[i].callbackObjPool[j]); + return true; + } + } + } + } + // not found + return false; } -static void radioTouchCallback(nbgl_obj_t *obj, nbgl_touchType_t eventType, nbgl_layoutInternal_t *layout); -static void longTouchCallback(nbgl_obj_t *obj, nbgl_touchType_t eventType, nbgl_layoutInternal_t *layout, layoutObj_t *layoutObj); +static void radioTouchCallback(nbgl_obj_t *obj, + nbgl_touchType_t eventType, + nbgl_layoutInternal_t *layout); +static void longTouchCallback(nbgl_obj_t *obj, + nbgl_touchType_t eventType, + nbgl_layoutInternal_t *layout, + layoutObj_t *layoutObj); // callback for most touched object -static void touchCallback(nbgl_obj_t *obj, nbgl_touchType_t eventType) { - nbgl_layoutInternal_t *layout; - layoutObj_t *layoutObj; - bool needRefresh = false; - - UNUSED(eventType); - - if (getLayoutAndLayoutObj(obj, &layout, &layoutObj) == false) { - // try with parent, if existing - if (getLayoutAndLayoutObj(obj->parent, &layout, &layoutObj) == false) { - LOG_WARN(LAYOUT_LOGGER,"touchCallback(): eventType = %d, obj = %p, no active layout or obj not found\n",eventType,obj); - return; - } - } - - // case of navigation bar - if ((obj->parent == (nbgl_obj_t *)layout->bottomContainer) && - (layout->bottomContainerUsage == PAGE_INDICATOR)) { - if (nbgl_navigationCallback(obj, eventType, layout->nbPages, &layout->activePage) == false) { - // navigation was impossible - return; - } - layoutObj->index = layout->activePage; - } - - // case of switch - if ((obj->type == CONTAINER) && - (((nbgl_container_t*)obj)->nbChildren >= 2) && - (((nbgl_container_t*)obj)->children[1] != NULL) && - (((nbgl_container_t*)obj)->children[1]->type == SWITCH)) { - nbgl_switch_t *lSwitch = (nbgl_switch_t*)((nbgl_container_t*)obj)->children[1]; - lSwitch->state = (lSwitch->state == ON_STATE)?OFF_STATE:ON_STATE; - nbgl_redrawObject((nbgl_obj_t *)lSwitch,false,false); - // refresh will be done after tune playback - needRefresh = true; - // index is used for state - layoutObj->index = lSwitch->state; - } - // case of radio - else if ((obj->type == CONTAINER) && - (((nbgl_container_t*)obj)->nbChildren == 2) && - (((nbgl_container_t*)obj)->children[1] != NULL) && - (((nbgl_container_t*)obj)->children[1]->type == RADIO_BUTTON)) { - radioTouchCallback(obj, eventType, layout); - return; - } - // case of long press - else if ((obj->type == CONTAINER) && - (((nbgl_container_t*)obj)->nbChildren == 4) && - (((nbgl_container_t*)obj)->children[3] != NULL) && - (((nbgl_container_t*)obj)->children[3]->type == PROGRESS_BAR)) { - longTouchCallback(obj, eventType, layout, layoutObj); - return; - } - LOG_DEBUG(LAYOUT_LOGGER,"touchCallback(): layout->callback = %p\n",layout->callback); - if (layout->callback != NULL) { -#ifdef HAVE_PIEZO_SOUND - if (layoutObj->tuneIdtuneId); +static void touchCallback(nbgl_obj_t *obj, nbgl_touchType_t eventType) +{ + nbgl_layoutInternal_t *layout; + layoutObj_t *layoutObj; + bool needRefresh = false; + + UNUSED(eventType); + + if (getLayoutAndLayoutObj(obj, &layout, &layoutObj) == false) { + // try with parent, if existing + if (getLayoutAndLayoutObj(obj->parent, &layout, &layoutObj) == false) { + LOG_WARN( + LAYOUT_LOGGER, + "touchCallback(): eventType = %d, obj = %p, no active layout or obj not found\n", + eventType, + obj); + return; + } + } + + // case of navigation bar + if ((obj->parent == (nbgl_obj_t *) layout->bottomContainer) + && (layout->bottomContainerUsage == PAGE_INDICATOR)) { + if (nbgl_navigationCallback(obj, eventType, layout->nbPages, &layout->activePage) + == false) { + // navigation was impossible + return; + } + layoutObj->index = layout->activePage; + } + + // case of switch + if ((obj->type == CONTAINER) && (((nbgl_container_t *) obj)->nbChildren >= 2) + && (((nbgl_container_t *) obj)->children[1] != NULL) + && (((nbgl_container_t *) obj)->children[1]->type == SWITCH)) { + nbgl_switch_t *lSwitch = (nbgl_switch_t *) ((nbgl_container_t *) obj)->children[1]; + lSwitch->state = (lSwitch->state == ON_STATE) ? OFF_STATE : ON_STATE; + nbgl_redrawObject((nbgl_obj_t *) lSwitch, false, false); + // refresh will be done after tune playback + needRefresh = true; + // index is used for state + layoutObj->index = lSwitch->state; + } + // case of radio + else if ((obj->type == CONTAINER) && (((nbgl_container_t *) obj)->nbChildren == 2) + && (((nbgl_container_t *) obj)->children[1] != NULL) + && (((nbgl_container_t *) obj)->children[1]->type == RADIO_BUTTON)) { + radioTouchCallback(obj, eventType, layout); + return; } -#endif // HAVE_PIEZO_SOUND - if (needRefresh) { - nbgl_refreshSpecial(FULL_COLOR_PARTIAL_REFRESH); + // case of long press + else if ((obj->type == CONTAINER) && (((nbgl_container_t *) obj)->nbChildren == 4) + && (((nbgl_container_t *) obj)->children[3] != NULL) + && (((nbgl_container_t *) obj)->children[3]->type == PROGRESS_BAR)) { + longTouchCallback(obj, eventType, layout, layoutObj); + return; + } + LOG_DEBUG(LAYOUT_LOGGER, "touchCallback(): layout->callback = %p\n", layout->callback); + if (layout->callback != NULL) { +#ifdef HAVE_PIEZO_SOUND + if (layoutObj->tuneId < NBGL_NO_TUNE) { + io_seproxyhal_play_tune(layoutObj->tuneId); + } +#endif // HAVE_PIEZO_SOUND + if (needRefresh) { + nbgl_refreshSpecial(FULL_COLOR_PARTIAL_REFRESH); + } + layout->callback(layoutObj->token, layoutObj->index); } - layout->callback(layoutObj->token,layoutObj->index); - } } // callback for long press button -static void longTouchCallback(nbgl_obj_t *obj, nbgl_touchType_t eventType, nbgl_layoutInternal_t *layout, layoutObj_t *layoutObj) { - nbgl_container_t *container = (nbgl_container_t *)obj; - // 4th child of container is the progress bar - nbgl_progress_bar_t *progressBar = (nbgl_progress_bar_t *)container->children[3]; - - LOG_DEBUG(LAYOUT_LOGGER,"longTouchCallback(): eventType = %d, obj = %p, gLayout[1].nbChildren = %d\n",eventType,obj,gLayout[1].nbChildren); - - // case of pressing a long press button - if (eventType == TOUCHING) { - uint32_t touchDuration = nbgl_touchGetTouchDuration(obj); - - // Compute the new progress bar state in % - uint8_t new_state = get_hold_to_approve_percent(touchDuration); - - // Ensure the callback is triggered once, - // when the progress bar state reaches 100% - bool trigger_callback = (new_state >= 100) && (progressBar->state < 100); - - // Cap progress bar state at 100% - if(new_state >= 100) { - new_state = 100; - } - - // Update progress bar state - if(new_state != progressBar->state) { - progressBar->state = new_state; - nbgl_redrawObject((nbgl_obj_t *)progressBar,false,false); - // Ensure progress bar is fully drawn - // before calling the callback. - nbgl_refreshSpecialWithPostRefresh(BLACK_AND_WHITE_FAST_REFRESH, POST_REFRESH_FORCE_POWER_ON); - } - - if (trigger_callback) { - // End of progress bar reached: trigger callback - if (layout->callback != NULL) { - layout->callback(layoutObj->token,layoutObj->index); - } - } - } - // case of releasing a long press button (or getting out of it) - else if ((eventType == TOUCH_RELEASED) || (eventType == OUT_OF_TOUCH)) { - progressBar->state = 0; - nbgl_redrawObject((nbgl_obj_t *)progressBar,false,false); - nbgl_refreshSpecialWithPostRefresh(BLACK_AND_WHITE_REFRESH, POST_REFRESH_FORCE_POWER_OFF); - } +static void longTouchCallback(nbgl_obj_t *obj, + nbgl_touchType_t eventType, + nbgl_layoutInternal_t *layout, + layoutObj_t *layoutObj) +{ + nbgl_container_t *container = (nbgl_container_t *) obj; + // 4th child of container is the progress bar + nbgl_progress_bar_t *progressBar = (nbgl_progress_bar_t *) container->children[3]; + + LOG_DEBUG(LAYOUT_LOGGER, + "longTouchCallback(): eventType = %d, obj = %p, gLayout[1].nbChildren = %d\n", + eventType, + obj, + gLayout[1].nbChildren); + + // case of pressing a long press button + if (eventType == TOUCHING) { + uint32_t touchDuration = nbgl_touchGetTouchDuration(obj); + + // Compute the new progress bar state in % + uint8_t new_state = get_hold_to_approve_percent(touchDuration); + + // Ensure the callback is triggered once, + // when the progress bar state reaches 100% + bool trigger_callback = (new_state >= 100) && (progressBar->state < 100); + + // Cap progress bar state at 100% + if (new_state >= 100) { + new_state = 100; + } + + // Update progress bar state + if (new_state != progressBar->state) { + progressBar->state = new_state; + nbgl_redrawObject((nbgl_obj_t *) progressBar, false, false); + // Ensure progress bar is fully drawn + // before calling the callback. + nbgl_refreshSpecialWithPostRefresh(BLACK_AND_WHITE_FAST_REFRESH, + POST_REFRESH_FORCE_POWER_ON); + } + + if (trigger_callback) { + // End of progress bar reached: trigger callback + if (layout->callback != NULL) { + layout->callback(layoutObj->token, layoutObj->index); + } + } + } + // case of releasing a long press button (or getting out of it) + else if ((eventType == TOUCH_RELEASED) || (eventType == OUT_OF_TOUCH)) { + progressBar->state = 0; + nbgl_redrawObject((nbgl_obj_t *) progressBar, false, false); + nbgl_refreshSpecialWithPostRefresh(BLACK_AND_WHITE_REFRESH, POST_REFRESH_FORCE_POWER_OFF); + } } // callback for radio button touch -static void radioTouchCallback(nbgl_obj_t *obj, nbgl_touchType_t eventType, nbgl_layoutInternal_t *layout) { - uint8_t i=NB_MAX_LAYOUTS, radioIndex=0, foundRadio = 0xFF, foundRadioIndex; - - if (eventType != TOUCHED) { - return; - } - - i = 0; - // parse all objs to find all containers of radio buttons - while (inbUsedCallbackObjs) { - if ((obj == (nbgl_obj_t *)layout->callbackObjPool[i].obj) && (layout->callbackObjPool[i].obj->type == CONTAINER)) { - nbgl_radio_t *radio = (nbgl_radio_t *)((nbgl_container_t*)layout->callbackObjPool[i].obj)->children[1]; - nbgl_text_area_t *textArea = (nbgl_text_area_t *)((nbgl_container_t*)layout->callbackObjPool[i].obj)->children[0]; - foundRadio = i; - foundRadioIndex = radioIndex; - // set text as active (black and bold) - textArea->textColor = BLACK; - textArea->fontId = BAGL_FONT_INTER_SEMIBOLD_24px; - // ensure that radio button is ON - radio->state = ON_STATE; - // redraw container - nbgl_redrawObject((nbgl_obj_t*)obj,NULL,false); - } - else if ((layout->callbackObjPool[i].obj->type == CONTAINER) && - (((nbgl_container_t*)layout->callbackObjPool[i].obj)->nbChildren == 2) && - (((nbgl_container_t*)layout->callbackObjPool[i].obj)->children[1]->type == RADIO_BUTTON)) { - nbgl_radio_t *radio = (nbgl_radio_t *)((nbgl_container_t*)layout->callbackObjPool[i].obj)->children[1]; - nbgl_text_area_t *textArea = (nbgl_text_area_t *)((nbgl_container_t*)layout->callbackObjPool[i].obj)->children[0]; - radioIndex++; - // set to OFF the one that was in ON - if (radio->state == ON_STATE) { - radio->state = OFF_STATE; - // set text it as inactive (gray and normal) - textArea->textColor = DARK_GRAY; - textArea->fontId = BAGL_FONT_INTER_REGULAR_24px; - // redraw container - nbgl_redrawObject((nbgl_obj_t*)layout->callbackObjPool[i].obj,NULL,false); - } - } - i++; - } - // call callback after redraw to avoid asynchronicity - if (foundRadio != 0xFF) { - if (layout->callback != NULL) { +static void radioTouchCallback(nbgl_obj_t *obj, + nbgl_touchType_t eventType, + nbgl_layoutInternal_t *layout) +{ + uint8_t i = NB_MAX_LAYOUTS, radioIndex = 0, foundRadio = 0xFF, foundRadioIndex; + + if (eventType != TOUCHED) { + return; + } + + i = 0; + // parse all objs to find all containers of radio buttons + while (i < layout->nbUsedCallbackObjs) { + if ((obj == (nbgl_obj_t *) layout->callbackObjPool[i].obj) + && (layout->callbackObjPool[i].obj->type == CONTAINER)) { + nbgl_radio_t *radio + = (nbgl_radio_t *) ((nbgl_container_t *) layout->callbackObjPool[i].obj) + ->children[1]; + nbgl_text_area_t *textArea + = (nbgl_text_area_t *) ((nbgl_container_t *) layout->callbackObjPool[i].obj) + ->children[0]; + foundRadio = i; + foundRadioIndex = radioIndex; + // set text as active (black and bold) + textArea->textColor = BLACK; + textArea->fontId = BAGL_FONT_INTER_SEMIBOLD_24px; + // ensure that radio button is ON + radio->state = ON_STATE; + // redraw container + nbgl_redrawObject((nbgl_obj_t *) obj, NULL, false); + } + else if ((layout->callbackObjPool[i].obj->type == CONTAINER) + && (((nbgl_container_t *) layout->callbackObjPool[i].obj)->nbChildren == 2) + && (((nbgl_container_t *) layout->callbackObjPool[i].obj)->children[1]->type + == RADIO_BUTTON)) { + nbgl_radio_t *radio + = (nbgl_radio_t *) ((nbgl_container_t *) layout->callbackObjPool[i].obj) + ->children[1]; + nbgl_text_area_t *textArea + = (nbgl_text_area_t *) ((nbgl_container_t *) layout->callbackObjPool[i].obj) + ->children[0]; + radioIndex++; + // set to OFF the one that was in ON + if (radio->state == ON_STATE) { + radio->state = OFF_STATE; + // set text it as inactive (gray and normal) + textArea->textColor = DARK_GRAY; + textArea->fontId = BAGL_FONT_INTER_REGULAR_24px; + // redraw container + nbgl_redrawObject((nbgl_obj_t *) layout->callbackObjPool[i].obj, NULL, false); + } + } + i++; + } + // call callback after redraw to avoid asynchronicity + if (foundRadio != 0xFF) { + if (layout->callback != NULL) { #ifdef HAVE_PIEZO_SOUND - if (layout->callbackObjPool[foundRadio].tuneIdcallbackObjPool[foundRadio].tuneId); - } - nbgl_refreshSpecial(FULL_COLOR_PARTIAL_REFRESH); -#endif // HAVE_PIEZO_SOUND - layout->callback(layout->callbackObjPool[foundRadio].token,foundRadioIndex); - } - } + if (layout->callbackObjPool[foundRadio].tuneId < NBGL_NO_TUNE) { + io_seproxyhal_play_tune(layout->callbackObjPool[foundRadio].tuneId); + } + nbgl_refreshSpecial(FULL_COLOR_PARTIAL_REFRESH); +#endif // HAVE_PIEZO_SOUND + layout->callback(layout->callbackObjPool[foundRadio].token, foundRadioIndex); + } + } } // callback for spinner ticker -static void spinnerTickerCallback(void) { - nbgl_spinner_t *spinner; - uint8_t i=0; - nbgl_layoutInternal_t *layout; - - // gLayout[1] is on top of gLayout[0] so if gLayout[1] is active, it must catch the event - if (gLayout[1].nbChildren > 0) { - layout = &gLayout[1]; - } - else { - layout = &gLayout[0]; - } - - // get index of obj - while (icontainer->nbChildren) { - if (layout->container->children[i]->type == SPINNER) { - spinner = (nbgl_spinner_t *)layout->container->children[i]; - spinner->position++; - spinner->position &= 3; // modulo 4 - nbgl_redrawObject((nbgl_obj_t*)spinner, NULL, false); - nbgl_refreshSpecial(BLACK_AND_WHITE_FAST_REFRESH); - return; - } - i++; - } +static void spinnerTickerCallback(void) +{ + nbgl_spinner_t *spinner; + uint8_t i = 0; + nbgl_layoutInternal_t *layout; + + // gLayout[1] is on top of gLayout[0] so if gLayout[1] is active, it must catch the event + if (gLayout[1].nbChildren > 0) { + layout = &gLayout[1]; + } + else { + layout = &gLayout[0]; + } + + // get index of obj + while (i < layout->container->nbChildren) { + if (layout->container->children[i]->type == SPINNER) { + spinner = (nbgl_spinner_t *) layout->container->children[i]; + spinner->position++; + spinner->position &= 3; // modulo 4 + nbgl_redrawObject((nbgl_obj_t *) spinner, NULL, false); + nbgl_refreshSpecial(BLACK_AND_WHITE_FAST_REFRESH); + return; + } + i++; + } } -static nbgl_line_t* createHorizontalLine(uint8_t layer) { - nbgl_line_t *line; +static nbgl_line_t *createHorizontalLine(uint8_t layer) +{ + nbgl_line_t *line; - line = (nbgl_line_t*)nbgl_objPoolGet(LINE,layer); - line->lineColor = LIGHT_GRAY; - line->obj.area.width = SCREEN_WIDTH; - line->obj.area.height = 4; - line->direction = HORIZONTAL; - line->thickness = 1; - return line; + line = (nbgl_line_t *) nbgl_objPoolGet(LINE, layer); + line->lineColor = LIGHT_GRAY; + line->obj.area.width = SCREEN_WIDTH; + line->obj.area.height = 4; + line->direction = HORIZONTAL; + line->thickness = 1; + return line; } -static nbgl_line_t* createLeftVerticalLine(uint8_t layer) { - nbgl_line_t *line; - - line = (nbgl_line_t*)nbgl_objPoolGet(LINE,layer); - line->lineColor = LIGHT_GRAY; - line->obj.area.width = 1; - line->obj.area.height = SCREEN_HEIGHT; - line->direction = VERTICAL; - line->thickness = 1; - line->obj.alignment = MID_LEFT; - return line; -} +static nbgl_line_t *createLeftVerticalLine(uint8_t layer) +{ + nbgl_line_t *line; -// function adding a layout object in the callbackObjPool array for the given layout, and configuring it -static layoutObj_t *addCallbackObj(nbgl_layoutInternal_t *layout, nbgl_obj_t *obj, uint8_t token, tune_index_e tuneId) { - layoutObj_t *layoutObj = NULL; + line = (nbgl_line_t *) nbgl_objPoolGet(LINE, layer); + line->lineColor = LIGHT_GRAY; + line->obj.area.width = 1; + line->obj.area.height = SCREEN_HEIGHT; + line->direction = VERTICAL; + line->thickness = 1; + line->obj.alignment = MID_LEFT; + return line; +} - if (layout->nbUsedCallbackObjs < (LAYOUT_OBJ_POOL_LEN-1)) { - layoutObj = &layout->callbackObjPool[layout->nbUsedCallbackObjs]; - layout->nbUsedCallbackObjs++; - layoutObj->obj = obj; - layoutObj->token = token; - layoutObj->tuneId = tuneId; - } +// function adding a layout object in the callbackObjPool array for the given layout, and +// configuring it +static layoutObj_t *addCallbackObj(nbgl_layoutInternal_t *layout, + nbgl_obj_t *obj, + uint8_t token, + tune_index_e tuneId) +{ + layoutObj_t *layoutObj = NULL; + + if (layout->nbUsedCallbackObjs < (LAYOUT_OBJ_POOL_LEN - 1)) { + layoutObj = &layout->callbackObjPool[layout->nbUsedCallbackObjs]; + layout->nbUsedCallbackObjs++; + layoutObj->obj = obj; + layoutObj->token = token; + layoutObj->tuneId = tuneId; + } - return layoutObj; + return layoutObj; } /** @@ -413,9 +464,10 @@ static layoutObj_t *addCallbackObj(nbgl_layoutInternal_t *layout, nbgl_obj_t *ob * @param layout * @param obj */ -static void addObjectToLayout(nbgl_layoutInternal_t *layout, nbgl_obj_t* obj) { - layout->container->children[layout->container->nbChildren] = obj; - layout->container->nbChildren++; +static void addObjectToLayout(nbgl_layoutInternal_t *layout, nbgl_obj_t *obj) +{ + layout->container->children[layout->container->nbChildren] = obj; + layout->container->nbChildren++; } /********************** @@ -428,74 +480,81 @@ static void addObjectToLayout(nbgl_layoutInternal_t *layout, nbgl_obj_t* obj) { * @param description description of layout * @return a pointer to the corresponding layout */ -nbgl_layout_t *nbgl_layoutGet(const nbgl_layoutDescription_t *description) { - nbgl_layoutInternal_t *layout = NULL; - - // find an empty layout in the proper "layer" - if (description->modal) { - if (gLayout[1].nbChildren == 0) { - layout = &gLayout[1]; - } - else if (gLayout[2].nbChildren == 0) { - layout = &gLayout[2]; - } - } - else { - // automatically "release" a potentially opened non-modal layout - gLayout[0].nbChildren = 0; - layout = &gLayout[0]; - } - if (layout == NULL) { - LOG_WARN(LAYOUT_LOGGER,"nbgl_layoutGet(): impossible to get a layout!\n"); - return NULL; - } - - // reset globals - memset(layout,0,sizeof(nbgl_layoutInternal_t)); - - layout->callback = (nbgl_layoutTouchCallback_t)PIC(description->onActionCallback); - layout->modal = description->modal; - layout->withLeftBorder = description->withLeftBorder; - if (description->modal) { - layout->layer = nbgl_screenPush(&layout->children, NB_MAX_SCREEN_CHILDREN, &description->ticker, (nbgl_touchCallback_t)touchCallback); - } - else { - nbgl_screenSet(&layout->children, NB_MAX_SCREEN_CHILDREN, &description->ticker, (nbgl_touchCallback_t)touchCallback); - layout->layer = 0; - } - layout->container = (nbgl_container_t*)nbgl_objPoolGet(CONTAINER,layout->layer); - layout->container->obj.area.width = SCREEN_WIDTH; - layout->container->obj.area.height = SCREEN_HEIGHT; - layout->container->layout = VERTICAL ; - layout->container->children = nbgl_containerPoolGet(NB_MAX_CONTAINER_CHILDREN,layout->layer); - layout->children[layout->nbChildren] = (nbgl_obj_t*)layout->container; - layout->nbChildren++; - - // if a tap text is defined, make the container tapable and display this text in gray - if (description->tapActionText != NULL) { - layoutObj_t *obj; - - obj = &layout->callbackObjPool[layout->nbUsedCallbackObjs]; - layout->nbUsedCallbackObjs++; - obj->obj = (nbgl_obj_t*)layout->container; - obj->token = description->tapActionToken; - obj->tuneId = description->tapTuneId; - layout->container->obj.touchMask = (1<tapText = (nbgl_text_area_t*)nbgl_objPoolGet(TEXT_AREA, 0); - layout->tapText->localized = false; - layout->tapText->text = PIC(description->tapActionText); - layout->tapText->textColor = DARK_GRAY; - layout->tapText->fontId = BAGL_FONT_INTER_REGULAR_24px; - layout->tapText->obj.area.width = SCREEN_WIDTH - 2*BORDER_MARGIN; - layout->tapText->obj.area.height = nbgl_getFontLineHeight(layout->tapText->fontId); - layout->tapText->textAlignment = CENTER; - layout->tapText->obj.alignmentMarginY = BORDER_MARGIN; - layout->tapText->obj.alignment = BOTTOM_MIDDLE; - } - - return (nbgl_layout_t*)layout; +nbgl_layout_t *nbgl_layoutGet(const nbgl_layoutDescription_t *description) +{ + nbgl_layoutInternal_t *layout = NULL; + + // find an empty layout in the proper "layer" + if (description->modal) { + if (gLayout[1].nbChildren == 0) { + layout = &gLayout[1]; + } + else if (gLayout[2].nbChildren == 0) { + layout = &gLayout[2]; + } + } + else { + // automatically "release" a potentially opened non-modal layout + gLayout[0].nbChildren = 0; + layout = &gLayout[0]; + } + if (layout == NULL) { + LOG_WARN(LAYOUT_LOGGER, "nbgl_layoutGet(): impossible to get a layout!\n"); + return NULL; + } + + // reset globals + memset(layout, 0, sizeof(nbgl_layoutInternal_t)); + + layout->callback = (nbgl_layoutTouchCallback_t) PIC(description->onActionCallback); + layout->modal = description->modal; + layout->withLeftBorder = description->withLeftBorder; + if (description->modal) { + layout->layer = nbgl_screenPush(&layout->children, + NB_MAX_SCREEN_CHILDREN, + &description->ticker, + (nbgl_touchCallback_t) touchCallback); + } + else { + nbgl_screenSet(&layout->children, + NB_MAX_SCREEN_CHILDREN, + &description->ticker, + (nbgl_touchCallback_t) touchCallback); + layout->layer = 0; + } + layout->container = (nbgl_container_t *) nbgl_objPoolGet(CONTAINER, layout->layer); + layout->container->obj.area.width = SCREEN_WIDTH; + layout->container->obj.area.height = SCREEN_HEIGHT; + layout->container->layout = VERTICAL; + layout->container->children = nbgl_containerPoolGet(NB_MAX_CONTAINER_CHILDREN, layout->layer); + layout->children[layout->nbChildren] = (nbgl_obj_t *) layout->container; + layout->nbChildren++; + + // if a tap text is defined, make the container tapable and display this text in gray + if (description->tapActionText != NULL) { + layoutObj_t *obj; + + obj = &layout->callbackObjPool[layout->nbUsedCallbackObjs]; + layout->nbUsedCallbackObjs++; + obj->obj = (nbgl_obj_t *) layout->container; + obj->token = description->tapActionToken; + obj->tuneId = description->tapTuneId; + layout->container->obj.touchMask = (1 << TOUCHED); + + // create 'tap to continue' text area + layout->tapText = (nbgl_text_area_t *) nbgl_objPoolGet(TEXT_AREA, 0); + layout->tapText->localized = false; + layout->tapText->text = PIC(description->tapActionText); + layout->tapText->textColor = DARK_GRAY; + layout->tapText->fontId = BAGL_FONT_INTER_REGULAR_24px; + layout->tapText->obj.area.width = SCREEN_WIDTH - 2 * BORDER_MARGIN; + layout->tapText->obj.area.height = nbgl_getFontLineHeight(layout->tapText->fontId); + layout->tapText->textAlignment = CENTER; + layout->tapText->obj.alignmentMarginY = BORDER_MARGIN; + layout->tapText->obj.alignment = BOTTOM_MIDDLE; + } + + return (nbgl_layout_t *) layout; } /** @@ -507,33 +566,39 @@ nbgl_layout_t *nbgl_layoutGet(const nbgl_layoutDescription_t *description) { * @param tuneId if not @ref NBGL_NO_TUNE, a tune will be played when button is pressed * @return >= 0 if OK */ -int nbgl_layoutAddTopRightButton(nbgl_layout_t *layout, const nbgl_icon_details_t *icon, uint8_t token, tune_index_e tuneId) { - nbgl_layoutInternal_t *layoutInt = (nbgl_layoutInternal_t *)layout; - layoutObj_t *obj; - nbgl_button_t *button; - - LOG_DEBUG(LAYOUT_LOGGER,"nbgl_layoutAddTopRightButton():\n"); - if (layout == NULL) - return -1; - button = (nbgl_button_t *)nbgl_objPoolGet(BUTTON,layoutInt->layer); - obj = addCallbackObj(layoutInt,(nbgl_obj_t*)button,token,tuneId); - if (obj == NULL) - return -1; - - addObjectToLayout(layoutInt,(nbgl_obj_t*)button); - button->obj.area.width = BUTTON_DIAMETER; - button->obj.area.height = BUTTON_DIAMETER; - button->radius = BUTTON_RADIUS; - button->obj.alignmentMarginX = BORDER_MARGIN; - button->obj.alignmentMarginY = BORDER_MARGIN; - button->foregroundColor = BLACK; - button->innerColor = WHITE; - button->borderColor = LIGHT_GRAY; - button->obj.touchMask = (1<icon = PIC(icon); - button->obj.alignment = TOP_RIGHT; - - return 0; +int nbgl_layoutAddTopRightButton(nbgl_layout_t *layout, + const nbgl_icon_details_t *icon, + uint8_t token, + tune_index_e tuneId) +{ + nbgl_layoutInternal_t *layoutInt = (nbgl_layoutInternal_t *) layout; + layoutObj_t *obj; + nbgl_button_t *button; + + LOG_DEBUG(LAYOUT_LOGGER, "nbgl_layoutAddTopRightButton():\n"); + if (layout == NULL) { + return -1; + } + button = (nbgl_button_t *) nbgl_objPoolGet(BUTTON, layoutInt->layer); + obj = addCallbackObj(layoutInt, (nbgl_obj_t *) button, token, tuneId); + if (obj == NULL) { + return -1; + } + + addObjectToLayout(layoutInt, (nbgl_obj_t *) button); + button->obj.area.width = BUTTON_DIAMETER; + button->obj.area.height = BUTTON_DIAMETER; + button->radius = BUTTON_RADIUS; + button->obj.alignmentMarginX = BORDER_MARGIN; + button->obj.alignmentMarginY = BORDER_MARGIN; + button->foregroundColor = BLACK; + button->innerColor = WHITE; + button->borderColor = LIGHT_GRAY; + button->obj.touchMask = (1 << TOUCHED); + button->icon = PIC(icon); + button->obj.alignment = TOP_RIGHT; + + return 0; } /** @@ -543,40 +608,45 @@ int nbgl_layoutAddTopRightButton(nbgl_layout_t *layout, const nbgl_icon_details_ * @param info structure giving the description of the navigation bar * @return >= 0 if OK */ -int nbgl_layoutAddNavigationBar(nbgl_layout_t *layout, const nbgl_layoutNavigationBar_t *info) { - nbgl_layoutInternal_t *layoutInt = (nbgl_layoutInternal_t *)layout; - layoutObj_t *obj; - - LOG_DEBUG(LAYOUT_LOGGER,"nbgl_layoutAddNavigationBar():\n"); - if (layout == NULL) - return -1; - - layoutInt->bottomContainer = nbgl_navigationPopulate(info->nbPages, info->activePage, info->withExitKey, layoutInt->layer); - obj = addCallbackObj(layoutInt,(nbgl_obj_t*)layoutInt->bottomContainer,info->token,info->tuneId); - if (obj == NULL) - return -1; - - layoutInt->activePage = info->activePage; - layoutInt->nbPages = info->nbPages; - layoutInt->bottomContainer->obj.alignTo = NULL; - layoutInt->bottomContainer->obj.alignment = BOTTOM_MIDDLE; - layoutInt->bottomContainerUsage = PAGE_INDICATOR; // used for navigation bar - layoutInt->children[layoutInt->nbChildren] = (nbgl_obj_t*)layoutInt->bottomContainer; - layoutInt->nbChildren++; - - layoutInt->container->obj.area.height -= layoutInt->bottomContainer->obj.area.height; - - if (info->withSeparationLine) { - nbgl_line_t *line = createHorizontalLine(layoutInt->layer); - line->obj.alignTo = (nbgl_obj_t*)layoutInt->bottomContainer; - line->obj.alignment = TOP_MIDDLE; - layoutInt->children[layoutInt->nbChildren] = (nbgl_obj_t*)line; +int nbgl_layoutAddNavigationBar(nbgl_layout_t *layout, const nbgl_layoutNavigationBar_t *info) +{ + nbgl_layoutInternal_t *layoutInt = (nbgl_layoutInternal_t *) layout; + layoutObj_t *obj; + + LOG_DEBUG(LAYOUT_LOGGER, "nbgl_layoutAddNavigationBar():\n"); + if (layout == NULL) { + return -1; + } + + layoutInt->bottomContainer = nbgl_navigationPopulate( + info->nbPages, info->activePage, info->withExitKey, layoutInt->layer); + obj = addCallbackObj( + layoutInt, (nbgl_obj_t *) layoutInt->bottomContainer, info->token, info->tuneId); + if (obj == NULL) { + return -1; + } + + layoutInt->activePage = info->activePage; + layoutInt->nbPages = info->nbPages; + layoutInt->bottomContainer->obj.alignTo = NULL; + layoutInt->bottomContainer->obj.alignment = BOTTOM_MIDDLE; + layoutInt->bottomContainerUsage = PAGE_INDICATOR; // used for navigation bar + layoutInt->children[layoutInt->nbChildren] = (nbgl_obj_t *) layoutInt->bottomContainer; layoutInt->nbChildren++; - layoutInt->container->obj.area.height -= 4; - } + layoutInt->container->obj.area.height -= layoutInt->bottomContainer->obj.area.height; - return 0; + if (info->withSeparationLine) { + nbgl_line_t *line = createHorizontalLine(layoutInt->layer); + line->obj.alignTo = (nbgl_obj_t *) layoutInt->bottomContainer; + line->obj.alignment = TOP_MIDDLE; + layoutInt->children[layoutInt->nbChildren] = (nbgl_obj_t *) line; + layoutInt->nbChildren++; + + layoutInt->container->obj.area.height -= 4; + } + + return 0; } /** @@ -590,26 +660,33 @@ int nbgl_layoutAddNavigationBar(nbgl_layout_t *layout, const nbgl_layoutNavigati * @param tuneId if not @ref NBGL_NO_TUNE, a tune will be played when button is pressed * @return >= 0 if OK */ -int nbgl_layoutAddBottomButton(nbgl_layout_t *layout, const nbgl_icon_details_t *icon, uint8_t token, bool separationLine, tune_index_e tuneId) { - nbgl_layoutInternal_t *layoutInt = (nbgl_layoutInternal_t *)layout; - layoutObj_t *obj; - - LOG_DEBUG(LAYOUT_LOGGER,"nbgl_layoutAddBottomButton():\n"); - if (layout == NULL) - return -1; - - layoutInt->bottomContainer = nbgl_bottomButtonPopulate(icon,separationLine,layoutInt->layer); - obj = addCallbackObj(layoutInt,(nbgl_obj_t*)layoutInt->bottomContainer,token,tuneId); - if (obj == NULL) - return -1; - layoutInt->bottomContainer->obj.alignment = BOTTOM_MIDDLE; - layoutInt->bottomContainerUsage = BUTTON; // used for a button - layoutInt->children[layoutInt->nbChildren] = (nbgl_obj_t*)layoutInt->bottomContainer; - layoutInt->nbChildren++; - - layoutInt->container->obj.area.height -= layoutInt->bottomContainer->obj.area.height; - - return 0; +int nbgl_layoutAddBottomButton(nbgl_layout_t *layout, + const nbgl_icon_details_t *icon, + uint8_t token, + bool separationLine, + tune_index_e tuneId) +{ + nbgl_layoutInternal_t *layoutInt = (nbgl_layoutInternal_t *) layout; + layoutObj_t *obj; + + LOG_DEBUG(LAYOUT_LOGGER, "nbgl_layoutAddBottomButton():\n"); + if (layout == NULL) { + return -1; + } + + layoutInt->bottomContainer = nbgl_bottomButtonPopulate(icon, separationLine, layoutInt->layer); + obj = addCallbackObj(layoutInt, (nbgl_obj_t *) layoutInt->bottomContainer, token, tuneId); + if (obj == NULL) { + return -1; + } + layoutInt->bottomContainer->obj.alignment = BOTTOM_MIDDLE; + layoutInt->bottomContainerUsage = BUTTON; // used for a button + layoutInt->children[layoutInt->nbChildren] = (nbgl_obj_t *) layoutInt->bottomContainer; + layoutInt->nbChildren++; + + layoutInt->container->obj.area.height -= layoutInt->bottomContainer->obj.area.height; + + return 0; } /** @@ -619,117 +696,125 @@ int nbgl_layoutAddBottomButton(nbgl_layout_t *layout, const nbgl_icon_details_t * @param barLayout the properties of the bar * @return >= 0 if OK */ -int nbgl_layoutAddTouchableBar(nbgl_layout_t *layout, const nbgl_layoutBar_t *barLayout) { - nbgl_layoutInternal_t *layoutInt = (nbgl_layoutInternal_t *)layout; - layoutObj_t *obj; - nbgl_text_area_t *textArea; - nbgl_image_t *imageLeft=NULL, *imageRight=NULL; - nbgl_container_t *container; - color_t color = (barLayout->inactive != true)? BLACK:LIGHT_GRAY; - - LOG_DEBUG(LAYOUT_LOGGER,"nbgl_layoutAddTouchableBar():\n"); - if (layout == NULL) - return -1; - - container = (nbgl_container_t *)nbgl_objPoolGet(CONTAINER,layoutInt->layer); - obj = addCallbackObj(layoutInt,(nbgl_obj_t*)container,barLayout->token,barLayout->tuneId); - if (obj == NULL) - return -1; - - // get container children (up to 4) - container->children = nbgl_containerPoolGet(4,layoutInt->layer); - container->nbChildren = 0; - - container->obj.area.width = AVAILABLE_WIDTH; - container->obj.area.height = TOUCHABLE_BAR_HEIGHT; - container->layout = HORIZONTAL; - container->obj.alignmentMarginX = BORDER_MARGIN; - container->obj.alignment = NO_ALIGNMENT; - container->obj.alignTo = NULL; - // the bar can only be touched if not inactive AND if one of the icon is present - // otherwise it is seen as a title - if ((barLayout->inactive != true) && ((barLayout->iconLeft != NULL)||(barLayout->iconRight != NULL))) { - container->obj.touchMask = (1<iconLeft != NULL) { - imageLeft = (nbgl_image_t *)nbgl_objPoolGet(IMAGE,layoutInt->layer); - imageLeft->foregroundColor = color; - imageLeft->buffer = PIC(barLayout->iconLeft); - imageLeft->obj.alignment = MID_LEFT; - imageLeft->obj.alignTo = (nbgl_obj_t*)NULL; - container->children[container->nbChildren] = (nbgl_obj_t*)imageLeft; - container->nbChildren++; - } - if (barLayout->text != NULL) { - textArea = (nbgl_text_area_t *)nbgl_objPoolGet(TEXT_AREA,layoutInt->layer); - textArea->textColor = color; - textArea->text = PIC(barLayout->text); - textArea->onDrawCallback = NULL; - textArea->fontId = BAGL_FONT_INTER_SEMIBOLD_24px; - textArea->obj.area.width = container->obj.area.width; - if (barLayout->iconLeft != NULL) - textArea->obj.area.width -= imageLeft->buffer->width+12; - if (barLayout->iconRight != NULL) - textArea->obj.area.width -= ((nbgl_icon_details_t *)PIC(barLayout->iconRight))->width; - textArea->obj.area.height = container->obj.area.height; - textArea->style = NO_STYLE; - if ((barLayout->iconLeft != NULL) && (barLayout->centered != true)) - textArea->obj.alignmentMarginX = 12; - if (barLayout->iconLeft != NULL) { - textArea->obj.alignTo = (nbgl_obj_t*)imageLeft; - textArea->obj.alignment = MID_RIGHT; +int nbgl_layoutAddTouchableBar(nbgl_layout_t *layout, const nbgl_layoutBar_t *barLayout) +{ + nbgl_layoutInternal_t *layoutInt = (nbgl_layoutInternal_t *) layout; + layoutObj_t *obj; + nbgl_text_area_t *textArea; + nbgl_image_t *imageLeft = NULL, *imageRight = NULL; + nbgl_container_t *container; + color_t color = (barLayout->inactive != true) ? BLACK : LIGHT_GRAY; + + LOG_DEBUG(LAYOUT_LOGGER, "nbgl_layoutAddTouchableBar():\n"); + if (layout == NULL) { + return -1; } - else { - textArea->obj.alignTo = (nbgl_obj_t*)NULL; - textArea->obj.alignment = NO_ALIGNMENT; + + container = (nbgl_container_t *) nbgl_objPoolGet(CONTAINER, layoutInt->layer); + obj = addCallbackObj(layoutInt, (nbgl_obj_t *) container, barLayout->token, barLayout->tuneId); + if (obj == NULL) { + return -1; } - if (barLayout->centered != true) { - textArea->textAlignment = MID_LEFT; + + // get container children (up to 4) + container->children = nbgl_containerPoolGet(4, layoutInt->layer); + container->nbChildren = 0; + + container->obj.area.width = AVAILABLE_WIDTH; + container->obj.area.height = TOUCHABLE_BAR_HEIGHT; + container->layout = HORIZONTAL; + container->obj.alignmentMarginX = BORDER_MARGIN; + container->obj.alignment = NO_ALIGNMENT; + container->obj.alignTo = NULL; + // the bar can only be touched if not inactive AND if one of the icon is present + // otherwise it is seen as a title + if ((barLayout->inactive != true) + && ((barLayout->iconLeft != NULL) || (barLayout->iconRight != NULL))) { + container->obj.touchMask = (1 << TOUCHED); } - else { - textArea->textAlignment = CENTER; + + if (barLayout->iconLeft != NULL) { + imageLeft = (nbgl_image_t *) nbgl_objPoolGet(IMAGE, layoutInt->layer); + imageLeft->foregroundColor = color; + imageLeft->buffer = PIC(barLayout->iconLeft); + imageLeft->obj.alignment = MID_LEFT; + imageLeft->obj.alignTo = (nbgl_obj_t *) NULL; + container->children[container->nbChildren] = (nbgl_obj_t *) imageLeft; + container->nbChildren++; } - textArea->wrapping = true; - container->children[container->nbChildren] = (nbgl_obj_t*)textArea; - container->nbChildren++; - } - if (barLayout->iconRight != NULL) { - imageRight = (nbgl_image_t *)nbgl_objPoolGet(IMAGE,layoutInt->layer); - imageRight->foregroundColor = color; - imageRight->buffer = PIC(barLayout->iconRight); - imageRight->obj.alignment = MID_RIGHT; - if (barLayout->text == NULL) { - imageRight->obj.alignTo = (nbgl_obj_t*)NULL; + if (barLayout->text != NULL) { + textArea = (nbgl_text_area_t *) nbgl_objPoolGet(TEXT_AREA, layoutInt->layer); + textArea->textColor = color; + textArea->text = PIC(barLayout->text); + textArea->onDrawCallback = NULL; + textArea->fontId = BAGL_FONT_INTER_SEMIBOLD_24px; + textArea->obj.area.width = container->obj.area.width; + if (barLayout->iconLeft != NULL) { + textArea->obj.area.width -= imageLeft->buffer->width + 12; + } + if (barLayout->iconRight != NULL) { + textArea->obj.area.width -= ((nbgl_icon_details_t *) PIC(barLayout->iconRight))->width; + } + textArea->obj.area.height = container->obj.area.height; + textArea->style = NO_STYLE; + if ((barLayout->iconLeft != NULL) && (barLayout->centered != true)) { + textArea->obj.alignmentMarginX = 12; + } + if (barLayout->iconLeft != NULL) { + textArea->obj.alignTo = (nbgl_obj_t *) imageLeft; + textArea->obj.alignment = MID_RIGHT; + } + else { + textArea->obj.alignTo = (nbgl_obj_t *) NULL; + textArea->obj.alignment = NO_ALIGNMENT; + } + if (barLayout->centered != true) { + textArea->textAlignment = MID_LEFT; + } + else { + textArea->textAlignment = CENTER; + } + textArea->wrapping = true; + container->children[container->nbChildren] = (nbgl_obj_t *) textArea; + container->nbChildren++; } - else { - imageRight->obj.alignTo = (nbgl_obj_t*)container->children[container->nbChildren-1]; + if (barLayout->iconRight != NULL) { + imageRight = (nbgl_image_t *) nbgl_objPoolGet(IMAGE, layoutInt->layer); + imageRight->foregroundColor = color; + imageRight->buffer = PIC(barLayout->iconRight); + imageRight->obj.alignment = MID_RIGHT; + if (barLayout->text == NULL) { + imageRight->obj.alignTo = (nbgl_obj_t *) NULL; + } + else { + imageRight->obj.alignTo = (nbgl_obj_t *) container->children[container->nbChildren - 1]; + } + container->children[container->nbChildren] = (nbgl_obj_t *) imageRight; + container->nbChildren++; + } + if (barLayout->subText != NULL) { + textArea = (nbgl_text_area_t *) nbgl_objPoolGet(TEXT_AREA, layoutInt->layer); + + textArea->textColor = BLACK; + textArea->text = PIC(barLayout->subText); + textArea->textAlignment = MID_LEFT; + textArea->fontId = BAGL_FONT_INTER_REGULAR_24px; + textArea->style = NO_STYLE; + textArea->wrapping = true; + textArea->obj.alignment = BOTTOM_LEFT; + textArea->obj.alignmentMarginY = BORDER_MARGIN; + textArea->obj.area.width = container->obj.area.width; + textArea->obj.area.height = nbgl_getTextHeightInWidth( + textArea->fontId, textArea->text, textArea->obj.area.width, textArea->wrapping); + container->children[container->nbChildren] = (nbgl_obj_t *) textArea; + container->nbChildren++; + container->obj.area.height += textArea->obj.area.height + 16; } - container->children[container->nbChildren] = (nbgl_obj_t*)imageRight; - container->nbChildren++; - } - if (barLayout->subText != NULL) { - textArea = (nbgl_text_area_t *)nbgl_objPoolGet(TEXT_AREA,layoutInt->layer); - - textArea->textColor = BLACK; - textArea->text = PIC(barLayout->subText); - textArea->textAlignment = MID_LEFT; - textArea->fontId = BAGL_FONT_INTER_REGULAR_24px; - textArea->style = NO_STYLE; - textArea->wrapping = true; - textArea->obj.alignment = BOTTOM_LEFT; - textArea->obj.alignmentMarginY = BORDER_MARGIN; - textArea->obj.area.width = container->obj.area.width; - textArea->obj.area.height = nbgl_getTextHeightInWidth(textArea->fontId, textArea->text, textArea->obj.area.width, textArea->wrapping); - container->children[container->nbChildren] = (nbgl_obj_t*)textArea; - container->nbChildren++; - container->obj.area.height += textArea->obj.area.height+16; - } - // set this new container as child of main container - addObjectToLayout(layoutInt,(nbgl_obj_t*)container); + // set this new container as child of main container + addObjectToLayout(layoutInt, (nbgl_obj_t *) container); - return 0; + return 0; } /** @@ -739,73 +824,80 @@ int nbgl_layoutAddTouchableBar(nbgl_layout_t *layout, const nbgl_layoutBar_t *ba * @param switchLayout description of the parameters of the switch * @return >= 0 if OK */ -int nbgl_layoutAddSwitch(nbgl_layout_t *layout, const nbgl_layoutSwitch_t *switchLayout) { - nbgl_layoutInternal_t *layoutInt = (nbgl_layoutInternal_t *)layout; - layoutObj_t *obj; - nbgl_text_area_t *textArea; - nbgl_text_area_t *subTextArea; - nbgl_switch_t *switchObj; - nbgl_container_t *container; - - LOG_DEBUG(LAYOUT_LOGGER,"nbgl_layoutAddSwitch():\n"); - if (layout == NULL) - return -1; - container = (nbgl_container_t *)nbgl_objPoolGet(CONTAINER,layoutInt->layer); - obj = addCallbackObj(layoutInt,(nbgl_obj_t*)container,switchLayout->token,switchLayout->tuneId); - if (obj == NULL) - return -1; - - // get container children - container->children = nbgl_containerPoolGet(3,layoutInt->layer); - container->obj.area.width = AVAILABLE_WIDTH; - container->obj.area.height = 2*BORDER_MARGIN; - container->layout = VERTICAL; - container->obj.alignmentMarginX = BORDER_MARGIN; - container->obj.alignment = NO_ALIGNMENT; - container->obj.touchMask = (1<layer); - textArea->textColor = BLACK; - textArea->text = PIC(switchLayout->text); - textArea->textAlignment = MID_LEFT; - textArea->fontId = BAGL_FONT_INTER_SEMIBOLD_24px; - textArea->obj.area.width = container->obj.area.width - 60; // the switch icon has 60px width - textArea->obj.area.height = nbgl_getTextHeight(BAGL_FONT_INTER_SEMIBOLD_24px, textArea->text); - container->obj.area.height += textArea->obj.area.height; - textArea->obj.alignment = TOP_LEFT; - textArea->obj.alignmentMarginY = BORDER_MARGIN; - container->children[0] = (nbgl_obj_t*)textArea; - - switchObj = (nbgl_switch_t *)nbgl_objPoolGet(SWITCH,layoutInt->layer); - switchObj->onColor = BLACK; - switchObj->offColor = LIGHT_GRAY; - switchObj->state = switchLayout->initState; - switchObj->obj.alignment = MID_RIGHT; - switchObj->obj.alignTo = (nbgl_obj_t*)textArea; - container->children[1] = (nbgl_obj_t*)switchObj; - - if (switchLayout->subText != NULL) { - subTextArea = (nbgl_text_area_t *)nbgl_objPoolGet(TEXT_AREA, layoutInt->layer); - subTextArea->textColor = BLACK; - subTextArea->text = PIC(switchLayout->subText); - subTextArea->textAlignment = MID_LEFT; - subTextArea->fontId = BAGL_FONT_INTER_REGULAR_24px; - subTextArea->wrapping = true; - subTextArea->obj.area.width = container->obj.area.width; - subTextArea->obj.area.height = nbgl_getTextHeightInWidth(subTextArea->fontId, subTextArea->text, subTextArea->obj.area.width, subTextArea->wrapping); - container->obj.area.height += subTextArea->obj.area.height + INNER_MARGIN; - subTextArea->obj.alignment = NO_ALIGNMENT; - subTextArea->obj.alignmentMarginY = INNER_MARGIN; - container->children[2] = (nbgl_obj_t*)subTextArea; - container->nbChildren = 3; - } - else { - container->nbChildren = 2; - } - // set this new container as child of main container - addObjectToLayout(layoutInt,(nbgl_obj_t*)container); - - return 0; +int nbgl_layoutAddSwitch(nbgl_layout_t *layout, const nbgl_layoutSwitch_t *switchLayout) +{ + nbgl_layoutInternal_t *layoutInt = (nbgl_layoutInternal_t *) layout; + layoutObj_t *obj; + nbgl_text_area_t *textArea; + nbgl_text_area_t *subTextArea; + nbgl_switch_t *switchObj; + nbgl_container_t *container; + + LOG_DEBUG(LAYOUT_LOGGER, "nbgl_layoutAddSwitch():\n"); + if (layout == NULL) { + return -1; + } + container = (nbgl_container_t *) nbgl_objPoolGet(CONTAINER, layoutInt->layer); + obj = addCallbackObj( + layoutInt, (nbgl_obj_t *) container, switchLayout->token, switchLayout->tuneId); + if (obj == NULL) { + return -1; + } + + // get container children + container->children = nbgl_containerPoolGet(3, layoutInt->layer); + container->obj.area.width = AVAILABLE_WIDTH; + container->obj.area.height = 2 * BORDER_MARGIN; + container->layout = VERTICAL; + container->obj.alignmentMarginX = BORDER_MARGIN; + container->obj.alignment = NO_ALIGNMENT; + container->obj.touchMask = (1 << TOUCHED); + + textArea = (nbgl_text_area_t *) nbgl_objPoolGet(TEXT_AREA, layoutInt->layer); + textArea->textColor = BLACK; + textArea->text = PIC(switchLayout->text); + textArea->textAlignment = MID_LEFT; + textArea->fontId = BAGL_FONT_INTER_SEMIBOLD_24px; + textArea->obj.area.width = container->obj.area.width - 60; // the switch icon has 60px width + textArea->obj.area.height = nbgl_getTextHeight(BAGL_FONT_INTER_SEMIBOLD_24px, textArea->text); + container->obj.area.height += textArea->obj.area.height; + textArea->obj.alignment = TOP_LEFT; + textArea->obj.alignmentMarginY = BORDER_MARGIN; + container->children[0] = (nbgl_obj_t *) textArea; + + switchObj = (nbgl_switch_t *) nbgl_objPoolGet(SWITCH, layoutInt->layer); + switchObj->onColor = BLACK; + switchObj->offColor = LIGHT_GRAY; + switchObj->state = switchLayout->initState; + switchObj->obj.alignment = MID_RIGHT; + switchObj->obj.alignTo = (nbgl_obj_t *) textArea; + container->children[1] = (nbgl_obj_t *) switchObj; + + if (switchLayout->subText != NULL) { + subTextArea = (nbgl_text_area_t *) nbgl_objPoolGet(TEXT_AREA, layoutInt->layer); + subTextArea->textColor = BLACK; + subTextArea->text = PIC(switchLayout->subText); + subTextArea->textAlignment = MID_LEFT; + subTextArea->fontId = BAGL_FONT_INTER_REGULAR_24px; + subTextArea->wrapping = true; + subTextArea->obj.area.width = container->obj.area.width; + subTextArea->obj.area.height = nbgl_getTextHeightInWidth(subTextArea->fontId, + subTextArea->text, + subTextArea->obj.area.width, + subTextArea->wrapping); + container->obj.area.height += subTextArea->obj.area.height + INNER_MARGIN; + subTextArea->obj.alignment = NO_ALIGNMENT; + subTextArea->obj.alignmentMarginY = INNER_MARGIN; + container->children[2] = (nbgl_obj_t *) subTextArea; + container->nbChildren = 3; + } + else { + container->nbChildren = 2; + } + // set this new container as child of main container + addObjectToLayout(layoutInt, (nbgl_obj_t *) container); + + return 0; } /** @@ -816,73 +908,79 @@ int nbgl_layoutAddSwitch(nbgl_layout_t *layout, const nbgl_layoutSwitch_t *switc * @param subText description under main text (NULL terminated, single line, may be null) * @return >= 0 if OK */ -int nbgl_layoutAddText(nbgl_layout_t *layout, const char *text, const char *subText) { - nbgl_layoutInternal_t *layoutInt = (nbgl_layoutInternal_t *)layout; - nbgl_container_t *container; - nbgl_text_area_t *textArea; - nbgl_text_area_t *subTextArea; - uint16_t fullHeight = 0; - - LOG_DEBUG(LAYOUT_LOGGER,"nbgl_layoutAddText():\n"); - if (layout == NULL) - return -1; - container = (nbgl_container_t *)nbgl_objPoolGet(CONTAINER,layoutInt->layer); - - // get container children - if (text != NULL) - container->nbChildren++; - if (subText != NULL) - container->nbChildren++; +int nbgl_layoutAddText(nbgl_layout_t *layout, const char *text, const char *subText) +{ + nbgl_layoutInternal_t *layoutInt = (nbgl_layoutInternal_t *) layout; + nbgl_container_t *container; + nbgl_text_area_t *textArea; + nbgl_text_area_t *subTextArea; + uint16_t fullHeight = 0; + + LOG_DEBUG(LAYOUT_LOGGER, "nbgl_layoutAddText():\n"); + if (layout == NULL) { + return -1; + } + container = (nbgl_container_t *) nbgl_objPoolGet(CONTAINER, layoutInt->layer); - container->children = nbgl_containerPoolGet(container->nbChildren,layoutInt->layer); - container->obj.area.width = AVAILABLE_WIDTH; + // get container children + if (text != NULL) { + container->nbChildren++; + } + if (subText != NULL) { + container->nbChildren++; + } - if (text != NULL) { - textArea = (nbgl_text_area_t *)nbgl_objPoolGet(TEXT_AREA,layoutInt->layer); + container->children = nbgl_containerPoolGet(container->nbChildren, layoutInt->layer); + container->obj.area.width = AVAILABLE_WIDTH; - textArea->textColor = BLACK; - textArea->text = PIC(text); - textArea->textAlignment = MID_LEFT; - textArea->fontId = BAGL_FONT_INTER_SEMIBOLD_24px; - textArea->style = NO_STYLE; - textArea->wrapping = true; - textArea->obj.alignment = NO_ALIGNMENT; - textArea->obj.alignmentMarginY = BORDER_MARGIN; - textArea->obj.area.width = container->obj.area.width; - textArea->obj.area.height = nbgl_getTextHeightInWidth(textArea->fontId, textArea->text, textArea->obj.area.width, textArea->wrapping); - fullHeight += textArea->obj.area.height; - container->children[0] = (nbgl_obj_t*)textArea; - } - if (subText != NULL) { - subTextArea = (nbgl_text_area_t *)nbgl_objPoolGet(TEXT_AREA,layoutInt->layer); - subTextArea->textColor = BLACK; - subTextArea->text = PIC(subText); - subTextArea->fontId = BAGL_FONT_INTER_REGULAR_24px; - subTextArea->style = NO_STYLE; - subTextArea->wrapping = true; - subTextArea->obj.area.width = container->obj.area.width; - subTextArea->obj.area.height = nbgl_getTextHeightInWidth(subTextArea->fontId,subTextArea->text,subTextArea->obj.area.width,false); - subTextArea->textAlignment = MID_LEFT; - subTextArea->obj.alignment = NO_ALIGNMENT; - fullHeight += subTextArea->obj.area.height; if (text != NULL) { - subTextArea->obj.alignmentMarginY = INTERNAL_MARGIN; - fullHeight += INTERNAL_MARGIN; - container->children[1] = (nbgl_obj_t*)subTextArea; + textArea = (nbgl_text_area_t *) nbgl_objPoolGet(TEXT_AREA, layoutInt->layer); + + textArea->textColor = BLACK; + textArea->text = PIC(text); + textArea->textAlignment = MID_LEFT; + textArea->fontId = BAGL_FONT_INTER_SEMIBOLD_24px; + textArea->style = NO_STYLE; + textArea->wrapping = true; + textArea->obj.alignment = NO_ALIGNMENT; + textArea->obj.alignmentMarginY = BORDER_MARGIN; + textArea->obj.area.width = container->obj.area.width; + textArea->obj.area.height = nbgl_getTextHeightInWidth( + textArea->fontId, textArea->text, textArea->obj.area.width, textArea->wrapping); + fullHeight += textArea->obj.area.height; + container->children[0] = (nbgl_obj_t *) textArea; } - else { - subTextArea->obj.alignmentMarginY = BORDER_MARGIN; - container->children[0] = (nbgl_obj_t*)subTextArea; - } - } - container->obj.area.height = fullHeight+2*BORDER_MARGIN; - container->layout = VERTICAL; - container->obj.alignmentMarginX = BORDER_MARGIN; - container->obj.alignment = NO_ALIGNMENT; - // set this new obj as child of main container - addObjectToLayout(layoutInt,(nbgl_obj_t*)container); - - return 0; + if (subText != NULL) { + subTextArea = (nbgl_text_area_t *) nbgl_objPoolGet(TEXT_AREA, layoutInt->layer); + subTextArea->textColor = BLACK; + subTextArea->text = PIC(subText); + subTextArea->fontId = BAGL_FONT_INTER_REGULAR_24px; + subTextArea->style = NO_STYLE; + subTextArea->wrapping = true; + subTextArea->obj.area.width = container->obj.area.width; + subTextArea->obj.area.height = nbgl_getTextHeightInWidth( + subTextArea->fontId, subTextArea->text, subTextArea->obj.area.width, false); + subTextArea->textAlignment = MID_LEFT; + subTextArea->obj.alignment = NO_ALIGNMENT; + fullHeight += subTextArea->obj.area.height; + if (text != NULL) { + subTextArea->obj.alignmentMarginY = INTERNAL_MARGIN; + fullHeight += INTERNAL_MARGIN; + container->children[1] = (nbgl_obj_t *) subTextArea; + } + else { + subTextArea->obj.alignmentMarginY = BORDER_MARGIN; + container->children[0] = (nbgl_obj_t *) subTextArea; + } + } + container->obj.area.height = fullHeight + 2 * BORDER_MARGIN; + container->layout = VERTICAL; + container->obj.alignmentMarginX = BORDER_MARGIN; + container->obj.alignment = NO_ALIGNMENT; + // set this new obj as child of main container + addObjectToLayout(layoutInt, (nbgl_obj_t *) container); + + return 0; } /** @@ -892,35 +990,38 @@ int nbgl_layoutAddText(nbgl_layout_t *layout, const char *text, const char *subT * @param text text to be displayed (auto-wrap) * @return >= 0 if OK */ -int nbgl_layoutAddLargeCaseText(nbgl_layout_t *layout, const char *text) { - nbgl_layoutInternal_t *layoutInt = (nbgl_layoutInternal_t *)layout; - nbgl_text_area_t *textArea; - - LOG_DEBUG(LAYOUT_LOGGER,"nbgl_layoutAddLargeCaseText():\n"); - if (layout == NULL) - return -1; - textArea = (nbgl_text_area_t *)nbgl_objPoolGet(TEXT_AREA,layoutInt->layer); - - textArea->textColor = BLACK; - textArea->text = PIC(text); - textArea->textAlignment = MID_LEFT; - textArea->fontId = BAGL_FONT_INTER_MEDIUM_32px; - textArea->obj.area.width = AVAILABLE_WIDTH; - textArea->wrapping = true; - textArea->obj.area.height = nbgl_getTextHeightInWidth(textArea->fontId, textArea->text, textArea->obj.area.width, textArea->wrapping); - textArea->style = NO_STYLE; - textArea->obj.alignment = NO_ALIGNMENT; - textArea->obj.alignmentMarginX = BORDER_MARGIN; - textArea->obj.alignmentMarginY = BORDER_MARGIN; - // if first object of container, increase the margin from top - if (layoutInt->container->nbChildren == 0) { - textArea->obj.alignmentMarginY += BORDER_MARGIN; - } - - // set this new obj as child of main container - addObjectToLayout(layoutInt,(nbgl_obj_t*)textArea); - - return 0; +int nbgl_layoutAddLargeCaseText(nbgl_layout_t *layout, const char *text) +{ + nbgl_layoutInternal_t *layoutInt = (nbgl_layoutInternal_t *) layout; + nbgl_text_area_t *textArea; + + LOG_DEBUG(LAYOUT_LOGGER, "nbgl_layoutAddLargeCaseText():\n"); + if (layout == NULL) { + return -1; + } + textArea = (nbgl_text_area_t *) nbgl_objPoolGet(TEXT_AREA, layoutInt->layer); + + textArea->textColor = BLACK; + textArea->text = PIC(text); + textArea->textAlignment = MID_LEFT; + textArea->fontId = BAGL_FONT_INTER_MEDIUM_32px; + textArea->obj.area.width = AVAILABLE_WIDTH; + textArea->wrapping = true; + textArea->obj.area.height = nbgl_getTextHeightInWidth( + textArea->fontId, textArea->text, textArea->obj.area.width, textArea->wrapping); + textArea->style = NO_STYLE; + textArea->obj.alignment = NO_ALIGNMENT; + textArea->obj.alignmentMarginX = BORDER_MARGIN; + textArea->obj.alignmentMarginY = BORDER_MARGIN; + // if first object of container, increase the margin from top + if (layoutInt->container->nbChildren == 0) { + textArea->obj.alignmentMarginY += BORDER_MARGIN; + } + + // set this new obj as child of main container + addObjectToLayout(layoutInt, (nbgl_obj_t *) textArea); + + return 0; } /** @@ -930,89 +1031,92 @@ int nbgl_layoutAddLargeCaseText(nbgl_layout_t *layout, const char *text) { * @param choices structure giving the list of choices and the current selected one * @return >= 0 if OK */ -int nbgl_layoutAddRadioChoice(nbgl_layout_t *layout, const nbgl_layoutRadioChoice_t *choices) { - nbgl_layoutInternal_t *layoutInt = (nbgl_layoutInternal_t *)layout; - layoutObj_t *obj; - uint8_t i; - - LOG_DEBUG(LAYOUT_LOGGER,"nbgl_layoutAddRadioChoice():\n"); - if (layout == NULL) - return -1; - for (i=0;inbChoices;i++) { - nbgl_container_t *container; - nbgl_text_area_t *textArea; - nbgl_radio_t *button; - nbgl_line_t *line; - - container = (nbgl_container_t *)nbgl_objPoolGet(CONTAINER,layoutInt->layer); - textArea = (nbgl_text_area_t *)nbgl_objPoolGet(TEXT_AREA,layoutInt->layer); - button = (nbgl_radio_t *)nbgl_objPoolGet(RADIO_BUTTON,layoutInt->layer); - - obj = addCallbackObj(layoutInt,(nbgl_obj_t*)container,choices->token,choices->tuneId); - if (obj == NULL) - return -1; +int nbgl_layoutAddRadioChoice(nbgl_layout_t *layout, const nbgl_layoutRadioChoice_t *choices) +{ + nbgl_layoutInternal_t *layoutInt = (nbgl_layoutInternal_t *) layout; + layoutObj_t *obj; + uint8_t i; + + LOG_DEBUG(LAYOUT_LOGGER, "nbgl_layoutAddRadioChoice():\n"); + if (layout == NULL) { + return -1; + } + for (i = 0; i < choices->nbChoices; i++) { + nbgl_container_t *container; + nbgl_text_area_t *textArea; + nbgl_radio_t *button; + nbgl_line_t *line; + + container = (nbgl_container_t *) nbgl_objPoolGet(CONTAINER, layoutInt->layer); + textArea = (nbgl_text_area_t *) nbgl_objPoolGet(TEXT_AREA, layoutInt->layer); + button = (nbgl_radio_t *) nbgl_objPoolGet(RADIO_BUTTON, layoutInt->layer); + + obj = addCallbackObj(layoutInt, (nbgl_obj_t *) container, choices->token, choices->tuneId); + if (obj == NULL) { + return -1; + } - // get container children (max 2) - container->nbChildren = 2; - container->children = nbgl_containerPoolGet(container->nbChildren,layoutInt->layer); + // get container children (max 2) + container->nbChildren = 2; + container->children = nbgl_containerPoolGet(container->nbChildren, layoutInt->layer); - // init text area for this choice - if (choices->localized == true) { - textArea->localized = true; + // init text area for this choice + if (choices->localized == true) { + textArea->localized = true; #if defined(HAVE_LANGUAGE_PACK) - textArea->textId = choices->nameIds[i]; -#endif // defined(HAVE_LANGUAGE_PACK) - } - else { - textArea->text = PIC(choices->names[i]); - } + textArea->textId = choices->nameIds[i]; +#endif // defined(HAVE_LANGUAGE_PACK) + } + else { + textArea->text = PIC(choices->names[i]); + } - textArea->textAlignment = MID_LEFT; - textArea->obj.area.width = 300; - textArea->obj.area.height = 24; - textArea->style = NO_STYLE; - textArea->obj.alignment = MID_LEFT; - textArea->obj.alignTo = (nbgl_obj_t*)container; - container->children[0] = (nbgl_obj_t*)textArea; - - // init button for this choice - button->activeColor = BLACK; - button->borderColor = LIGHT_GRAY; - button->obj.alignmentMarginX = INNER_MARGIN-4; - button->obj.alignTo = (nbgl_obj_t*)container; - button->obj.alignment = MID_RIGHT; - button->state = OFF_STATE; - container->children[1] = (nbgl_obj_t*)button; - - container->obj.area.width = SCREEN_WIDTH-2*BORDER_MARGIN; - container->obj.area.height = 32; - container->obj.alignment = NO_ALIGNMENT; - container->obj.alignmentMarginX = BORDER_MARGIN; - container->obj.alignmentMarginY = BORDER_MARGIN; - container->obj.alignTo = (nbgl_obj_t*)NULL; - // whole container should be touchable - container->obj.touchMask = (1<textAlignment = MID_LEFT; + textArea->obj.area.width = 300; + textArea->obj.area.height = 24; + textArea->style = NO_STYLE; + textArea->obj.alignment = MID_LEFT; + textArea->obj.alignTo = (nbgl_obj_t *) container; + container->children[0] = (nbgl_obj_t *) textArea; + + // init button for this choice + button->activeColor = BLACK; + button->borderColor = LIGHT_GRAY; + button->obj.alignmentMarginX = INNER_MARGIN - 4; + button->obj.alignTo = (nbgl_obj_t *) container; + button->obj.alignment = MID_RIGHT; + button->state = OFF_STATE; + container->children[1] = (nbgl_obj_t *) button; + + container->obj.area.width = SCREEN_WIDTH - 2 * BORDER_MARGIN; + container->obj.area.height = 32; + container->obj.alignment = NO_ALIGNMENT; + container->obj.alignmentMarginX = BORDER_MARGIN; + container->obj.alignmentMarginY = BORDER_MARGIN; + container->obj.alignTo = (nbgl_obj_t *) NULL; + // whole container should be touchable + container->obj.touchMask = (1 << TOUCHED); + + // highlight init choice + if (i == choices->initChoice) { + button->state = ON_STATE; + textArea->textColor = BLACK; + textArea->fontId = BAGL_FONT_INTER_SEMIBOLD_24px; + } + else { + button->state = OFF_STATE; + textArea->textColor = DARK_GRAY; + textArea->fontId = BAGL_FONT_INTER_REGULAR_24px; + } + line = createHorizontalLine(layoutInt->layer); + line->obj.alignmentMarginY = BORDER_MARGIN; - // highlight init choice - if (i == choices->initChoice) { - button->state = ON_STATE; - textArea->textColor = BLACK; - textArea->fontId = BAGL_FONT_INTER_SEMIBOLD_24px; - } - else { - button->state = OFF_STATE; - textArea->textColor = DARK_GRAY; - textArea->fontId = BAGL_FONT_INTER_REGULAR_24px; + // set these new objs as child of main container + addObjectToLayout(layoutInt, (nbgl_obj_t *) container); + addObjectToLayout(layoutInt, (nbgl_obj_t *) line); } - line = createHorizontalLine(layoutInt->layer); - line->obj.alignmentMarginY = BORDER_MARGIN; - // set these new objs as child of main container - addObjectToLayout(layoutInt,(nbgl_obj_t*)container); - addObjectToLayout(layoutInt,(nbgl_obj_t*)line); - } - - return 0; + return 0; } /** @@ -1023,184 +1127,190 @@ int nbgl_layoutAddRadioChoice(nbgl_layout_t *layout, const nbgl_layoutRadioChoic * @param info structure giving the description of buttons (texts, icons, layout) * @return >= 0 if OK */ -int nbgl_layoutAddCenteredInfo(nbgl_layout_t *layout, const nbgl_layoutCenteredInfo_t *info) { - nbgl_layoutInternal_t *layoutInt = (nbgl_layoutInternal_t *)layout; - nbgl_container_t *container; - nbgl_text_area_t *textArea=NULL; - nbgl_image_t *image=NULL; - uint16_t fullHeight = 0; - - LOG_DEBUG(LAYOUT_LOGGER,"nbgl_layoutAddCenteredInfo():\n"); - if (layout == NULL) - return -1; - - container = (nbgl_container_t *)nbgl_objPoolGet(CONTAINER,layoutInt->layer); - - // get container children (max 5 if PLUGIN_INFO) - container->children = nbgl_containerPoolGet((info->style == PLUGIN_INFO)?5:4,layoutInt->layer); - container->nbChildren = 0; - - if (info->icon != NULL) { - image = (nbgl_image_t *)nbgl_objPoolGet(IMAGE,layoutInt->layer); - image->foregroundColor = BLACK; - image->buffer = PIC(info->icon); - image->obj.area.bpp = NBGL_BPP_1; - image->obj.alignment = TOP_MIDDLE; - image->obj.alignTo = NULL; - - fullHeight += image->buffer->height; - if ((info->style != PLUGIN_INFO)) { - container->children[container->nbChildren] = (nbgl_obj_t*)image; - container->nbChildren++; - } - } - if (info->text1 != NULL) { - textArea = (nbgl_text_area_t *)nbgl_objPoolGet(TEXT_AREA,layoutInt->layer); - textArea->textColor = BLACK; - textArea->text = PIC(info->text1); - textArea->textAlignment = CENTER; - if (info->style == LEDGER_INFO) { - textArea->fontId = BAGL_FONT_HM_ALPHA_MONO_MEDIUM_32px; - } - else if ((info->style == LARGE_CASE_INFO) || - (info->style == LARGE_CASE_BOLD_INFO) || - (info->style == PLUGIN_INFO)) { - textArea->fontId = BAGL_FONT_INTER_MEDIUM_32px; +int nbgl_layoutAddCenteredInfo(nbgl_layout_t *layout, const nbgl_layoutCenteredInfo_t *info) +{ + nbgl_layoutInternal_t *layoutInt = (nbgl_layoutInternal_t *) layout; + nbgl_container_t *container; + nbgl_text_area_t *textArea = NULL; + nbgl_image_t *image = NULL; + uint16_t fullHeight = 0; + + LOG_DEBUG(LAYOUT_LOGGER, "nbgl_layoutAddCenteredInfo():\n"); + if (layout == NULL) { + return -1; } - else { - textArea->fontId = BAGL_FONT_INTER_SEMIBOLD_24px; - } - textArea->wrapping = true; - textArea->obj.area.width = AVAILABLE_WIDTH; - textArea->obj.area.height = nbgl_getTextHeightInWidth(textArea->fontId, textArea->text, textArea->obj.area.width, textArea->wrapping); - if (info->style == LEDGER_INFO) { - textArea->style = LEDGER_BORDER; - textArea->obj.area.width = SCREEN_WIDTH - 2*40; - textArea->obj.area.height += 2*16; - } - else - textArea->style = NO_STYLE; - if (container->nbChildren>0) { - textArea->obj.alignment = BOTTOM_MIDDLE; - textArea->obj.alignTo = (nbgl_obj_t*)container->children[container->nbChildren-1]; - textArea->obj.alignmentMarginY = BORDER_MARGIN+4; - } - else { - textArea->obj.alignment = TOP_MIDDLE; - textArea->obj.alignTo = NULL; + container = (nbgl_container_t *) nbgl_objPoolGet(CONTAINER, layoutInt->layer); + + // get container children (max 5 if PLUGIN_INFO) + container->children + = nbgl_containerPoolGet((info->style == PLUGIN_INFO) ? 5 : 4, layoutInt->layer); + container->nbChildren = 0; + + if (info->icon != NULL) { + image = (nbgl_image_t *) nbgl_objPoolGet(IMAGE, layoutInt->layer); + image->foregroundColor = BLACK; + image->buffer = PIC(info->icon); + image->obj.area.bpp = NBGL_BPP_1; + image->obj.alignment = TOP_MIDDLE; + image->obj.alignTo = NULL; + + fullHeight += image->buffer->height; + if ((info->style != PLUGIN_INFO)) { + container->children[container->nbChildren] = (nbgl_obj_t *) image; + container->nbChildren++; + } } + if (info->text1 != NULL) { + textArea = (nbgl_text_area_t *) nbgl_objPoolGet(TEXT_AREA, layoutInt->layer); + textArea->textColor = BLACK; + textArea->text = PIC(info->text1); + textArea->textAlignment = CENTER; + if (info->style == LEDGER_INFO) { + textArea->fontId = BAGL_FONT_HM_ALPHA_MONO_MEDIUM_32px; + } + else if ((info->style == LARGE_CASE_INFO) || (info->style == LARGE_CASE_BOLD_INFO) + || (info->style == PLUGIN_INFO)) { + textArea->fontId = BAGL_FONT_INTER_MEDIUM_32px; + } + else { + textArea->fontId = BAGL_FONT_INTER_SEMIBOLD_24px; + } + textArea->wrapping = true; + textArea->obj.area.width = AVAILABLE_WIDTH; + textArea->obj.area.height = nbgl_getTextHeightInWidth( + textArea->fontId, textArea->text, textArea->obj.area.width, textArea->wrapping); + + if (info->style == LEDGER_INFO) { + textArea->style = LEDGER_BORDER; + textArea->obj.area.width = SCREEN_WIDTH - 2 * 40; + textArea->obj.area.height += 2 * 16; + } + else { + textArea->style = NO_STYLE; + } + if (container->nbChildren > 0) { + textArea->obj.alignment = BOTTOM_MIDDLE; + textArea->obj.alignTo = (nbgl_obj_t *) container->children[container->nbChildren - 1]; + textArea->obj.alignmentMarginY = BORDER_MARGIN + 4; + } + else { + textArea->obj.alignment = TOP_MIDDLE; + textArea->obj.alignTo = NULL; + } - fullHeight += textArea->obj.area.height+textArea->obj.alignmentMarginY; + fullHeight += textArea->obj.area.height + textArea->obj.alignmentMarginY; - container->children[container->nbChildren] = (nbgl_obj_t*)textArea; - container->nbChildren++; - } - if (info->text2 != NULL) { - textArea = (nbgl_text_area_t *)nbgl_objPoolGet(TEXT_AREA,layoutInt->layer); - if ((info->style != LARGE_CASE_INFO) && - (info->style != LARGE_CASE_BOLD_INFO) && - (info->style != PLUGIN_INFO)) { - textArea->textColor = DARK_GRAY; + container->children[container->nbChildren] = (nbgl_obj_t *) textArea; + container->nbChildren++; } - else { - textArea->textColor = BLACK; - } - textArea->text = PIC(info->text2); - textArea->textAlignment = CENTER; - textArea->fontId = (info->style != LARGE_CASE_BOLD_INFO) ? BAGL_FONT_INTER_REGULAR_24px: BAGL_FONT_INTER_SEMIBOLD_24px; - textArea->wrapping = true; - textArea->obj.area.width = AVAILABLE_WIDTH; - textArea->obj.area.height = nbgl_getTextHeightInWidth(textArea->fontId, textArea->text, textArea->obj.area.width, textArea->wrapping); + if (info->text2 != NULL) { + textArea = (nbgl_text_area_t *) nbgl_objPoolGet(TEXT_AREA, layoutInt->layer); + if ((info->style != LARGE_CASE_INFO) && (info->style != LARGE_CASE_BOLD_INFO) + && (info->style != PLUGIN_INFO)) { + textArea->textColor = DARK_GRAY; + } + else { + textArea->textColor = BLACK; + } + textArea->text = PIC(info->text2); + textArea->textAlignment = CENTER; + textArea->fontId = (info->style != LARGE_CASE_BOLD_INFO) ? BAGL_FONT_INTER_REGULAR_24px + : BAGL_FONT_INTER_SEMIBOLD_24px; + textArea->wrapping = true; + textArea->obj.area.width = AVAILABLE_WIDTH; + textArea->obj.area.height = nbgl_getTextHeightInWidth( + textArea->fontId, textArea->text, textArea->obj.area.width, textArea->wrapping); + + textArea->style = NO_STYLE; + if (container->nbChildren > 0) { + textArea->obj.alignment = BOTTOM_MIDDLE; + textArea->obj.alignTo = (nbgl_obj_t *) container->children[container->nbChildren - 1]; + textArea->obj.alignmentMarginY = BORDER_MARGIN; + if (info->text1 != NULL) { + // if previous element is text1, only space of 16 px + textArea->obj.alignmentMarginY -= 4; + } + else { + // else if icon, space of 24 px + textArea->obj.alignmentMarginY += 4; + } + } + else { + textArea->obj.alignment = TOP_MIDDLE; + } - textArea->style = NO_STYLE; - if (container->nbChildren>0) { - textArea->obj.alignment = BOTTOM_MIDDLE; - textArea->obj.alignTo = (nbgl_obj_t*)container->children[container->nbChildren-1]; - textArea->obj.alignmentMarginY = BORDER_MARGIN; - if (info->text1 != NULL) { - // if previous element is text1, only space of 16 px - textArea->obj.alignmentMarginY -= 4; - } - else { - // else if icon, space of 24 px - textArea->obj.alignmentMarginY += 4; - } + fullHeight += textArea->obj.area.height + textArea->obj.alignmentMarginY; + + container->children[container->nbChildren] = (nbgl_obj_t *) textArea; + container->nbChildren++; } - else { - textArea->obj.alignment = TOP_MIDDLE; + // draw small horizontal line if PLUGIN_INFO + if (info->style == PLUGIN_INFO) { + nbgl_line_t *line = createHorizontalLine(layoutInt->layer); + line->obj.area.width = 120; + line->obj.alignmentMarginY = 32; + line->obj.alignmentMarginX = 0; + line->obj.alignment = BOTTOM_MIDDLE; + line->obj.alignTo = (nbgl_obj_t *) container->children[container->nbChildren - 1]; + fullHeight += 32; + + container->children[container->nbChildren] = (nbgl_obj_t *) line; + container->nbChildren++; + if (image) { + // add icon here, under line + image->obj.alignmentMarginY = 32; + image->obj.alignment = BOTTOM_MIDDLE; + image->obj.alignTo = (nbgl_obj_t *) container->children[container->nbChildren - 1]; + container->children[container->nbChildren] = (nbgl_obj_t *) image; + container->nbChildren++; + fullHeight += 32; + } } + if (info->text3 != NULL) { + textArea = (nbgl_text_area_t *) nbgl_objPoolGet(TEXT_AREA, layoutInt->layer); + textArea->textColor = BLACK; + textArea->text = PIC(info->text3); + textArea->textAlignment = CENTER; + textArea->fontId = BAGL_FONT_INTER_REGULAR_24px; + textArea->wrapping = true; + textArea->obj.area.width = AVAILABLE_WIDTH; + textArea->obj.area.height = nbgl_getTextHeightInWidth( + textArea->fontId, textArea->text, textArea->obj.area.width, textArea->wrapping); + textArea->style = NO_STYLE; + if (container->nbChildren > 0) { + textArea->obj.alignment = BOTTOM_MIDDLE; + textArea->obj.alignTo = (nbgl_obj_t *) container->children[container->nbChildren - 1]; + textArea->obj.alignmentMarginY = BORDER_MARGIN; + } + else { + textArea->obj.alignment = TOP_MIDDLE; + textArea->obj.alignTo = NULL; + } - fullHeight += textArea->obj.area.height + textArea->obj.alignmentMarginY; + fullHeight += textArea->obj.area.height + textArea->obj.alignmentMarginY; - container->children[container->nbChildren] = (nbgl_obj_t*)textArea; - container->nbChildren++; - } - // draw small horizontal line if PLUGIN_INFO - if (info->style == PLUGIN_INFO) { - nbgl_line_t *line = createHorizontalLine(layoutInt->layer); - line->obj.area.width = 120; - line->obj.alignmentMarginY = 32; - line->obj.alignmentMarginX = 0; - line->obj.alignment = BOTTOM_MIDDLE; - line->obj.alignTo = (nbgl_obj_t*)container->children[container->nbChildren-1]; - fullHeight += 32; - - container->children[container->nbChildren] = (nbgl_obj_t*)line; - container->nbChildren++; - if (image) { - // add icon here, under line - image->obj.alignmentMarginY = 32; - image->obj.alignment = BOTTOM_MIDDLE; - image->obj.alignTo = (nbgl_obj_t*)container->children[container->nbChildren-1]; - container->children[container->nbChildren] = (nbgl_obj_t*)image; - container->nbChildren++; - fullHeight += 32; - } - } - if (info->text3 != NULL) { - textArea = (nbgl_text_area_t *)nbgl_objPoolGet(TEXT_AREA,layoutInt->layer); - textArea->textColor = BLACK; - textArea->text = PIC(info->text3); - textArea->textAlignment = CENTER; - textArea->fontId = BAGL_FONT_INTER_REGULAR_24px; - textArea->wrapping = true; - textArea->obj.area.width = AVAILABLE_WIDTH; - textArea->obj.area.height = nbgl_getTextHeightInWidth(textArea->fontId, textArea->text, textArea->obj.area.width, textArea->wrapping); - textArea->style = NO_STYLE; - if (container->nbChildren>0) { - textArea->obj.alignment = BOTTOM_MIDDLE; - textArea->obj.alignTo = (nbgl_obj_t*)container->children[container->nbChildren-1]; - textArea->obj.alignmentMarginY = BORDER_MARGIN; + container->children[container->nbChildren] = (nbgl_obj_t *) textArea; + container->nbChildren++; + } + container->obj.area.height = fullHeight; + container->layout = VERTICAL; + if (info->onTop) { + container->obj.alignmentMarginX = BORDER_MARGIN; + container->obj.alignmentMarginY = BORDER_MARGIN + info->offsetY; + container->obj.alignment = NO_ALIGNMENT; } else { - textArea->obj.alignment = TOP_MIDDLE; - textArea->obj.alignTo = NULL; + container->obj.alignmentMarginY = info->offsetY; + container->obj.alignment = CENTER; } - fullHeight += textArea->obj.area.height+textArea->obj.alignmentMarginY; + container->obj.area.width = AVAILABLE_WIDTH; - container->children[container->nbChildren] = (nbgl_obj_t*)textArea; - container->nbChildren++; - } - container->obj.area.height = fullHeight; - container->layout = VERTICAL; - if (info->onTop) { - container->obj.alignmentMarginX = BORDER_MARGIN; - container->obj.alignmentMarginY = BORDER_MARGIN+ info->offsetY; - container->obj.alignment = NO_ALIGNMENT; - } - else { - container->obj.alignmentMarginY = info->offsetY; - container->obj.alignment = CENTER; - } - - container->obj.area.width = AVAILABLE_WIDTH; - - // set this new container as child of main container - addObjectToLayout(layoutInt,(nbgl_obj_t*)container); + // set this new container as child of main container + addObjectToLayout(layoutInt, (nbgl_obj_t *) container); - return 0; + return 0; } #ifdef NBGL_QRCODE @@ -1212,101 +1322,108 @@ int nbgl_layoutAddCenteredInfo(nbgl_layout_t *layout, const nbgl_layoutCenteredI * @param info structure giving the description of buttons (texts, icons, layout) * @return >= 0 if OK */ -int nbgl_layoutAddQRCode(nbgl_layout_t *layout, const nbgl_layoutQRCode_t *info) { - nbgl_layoutInternal_t *layoutInt = (nbgl_layoutInternal_t *)layout; - nbgl_container_t *container; - nbgl_text_area_t *textArea=NULL; - nbgl_qrcode_t *qrcode; - uint16_t fullHeight = 0; - - LOG_DEBUG(LAYOUT_LOGGER,"nbgl_layoutAddQRCode():\n"); - if (layout == NULL) - return -1; - - container = (nbgl_container_t *)nbgl_objPoolGet(CONTAINER,layoutInt->layer); - - // get container children (max 2 (QRCode + text1/text2)) - container->children = nbgl_containerPoolGet(2, layoutInt->layer); - container->nbChildren = 0; - - qrcode = (nbgl_qrcode_t *)nbgl_objPoolGet(QR_CODE, layoutInt->layer); - // version is forced to V10 if url is longer than 62 characters - if (strlen(PIC(info->url)) > 62) { - qrcode->version = QRCODE_V10; - } - else { - qrcode->version = QRCODE_V4; - } - qrcode->foregroundColor = BLACK; - // in QR V4, we use 8*8 screen pixels for one QR pixel - // in QR V10, we use 4*4 screen pixels for one QR pixel - qrcode->obj.area.width = (qrcode->version == QRCODE_V4) ? (QR_V4_NB_PIX_SIZE * 8) : (QR_V10_NB_PIX_SIZE * 4); - qrcode->obj.area.height = qrcode->obj.area.width; - qrcode->text = PIC(info->url); - qrcode->obj.area.bpp = NBGL_BPP_1; - qrcode->obj.alignment = TOP_MIDDLE; - qrcode->obj.alignmentMarginY = 24; - - fullHeight += qrcode->obj.area.height; - container->children[container->nbChildren] = (nbgl_obj_t*)qrcode; - container->nbChildren++; - - if (info->text1 != NULL) { - textArea = (nbgl_text_area_t *)nbgl_objPoolGet(TEXT_AREA, layoutInt->layer); - textArea->textColor = BLACK; - textArea->text = PIC(info->text1); - textArea->textAlignment = CENTER; - textArea->fontId = (info->largeText1 == true)? BAGL_FONT_INTER_MEDIUM_32px : BAGL_FONT_INTER_REGULAR_24px; - textArea->wrapping = true; - textArea->obj.area.width = AVAILABLE_WIDTH; - textArea->obj.area.height = nbgl_getTextHeightInWidth(textArea->fontId, textArea->text, textArea->obj.area.width, textArea->wrapping); - textArea->obj.alignment = BOTTOM_MIDDLE; - textArea->obj.alignTo = (nbgl_obj_t*)container->children[container->nbChildren-1]; - textArea->obj.alignmentMarginY = 40; - - fullHeight += textArea->obj.area.height; +int nbgl_layoutAddQRCode(nbgl_layout_t *layout, const nbgl_layoutQRCode_t *info) +{ + nbgl_layoutInternal_t *layoutInt = (nbgl_layoutInternal_t *) layout; + nbgl_container_t *container; + nbgl_text_area_t *textArea = NULL; + nbgl_qrcode_t *qrcode; + uint16_t fullHeight = 0; + + LOG_DEBUG(LAYOUT_LOGGER, "nbgl_layoutAddQRCode():\n"); + if (layout == NULL) { + return -1; + } - container->children[container->nbChildren] = (nbgl_obj_t*)textArea; - container->nbChildren++; - } - else if (info->text2 != NULL) { - textArea = (nbgl_text_area_t *)nbgl_objPoolGet(TEXT_AREA, layoutInt->layer); - textArea->textColor = DARK_GRAY; - textArea->text = PIC(info->text2); - textArea->textAlignment = CENTER; - textArea->fontId = BAGL_FONT_INTER_REGULAR_24px; - textArea->wrapping = true; - textArea->obj.area.width = AVAILABLE_WIDTH; - textArea->obj.area.height = nbgl_getTextHeightInWidth(textArea->fontId, textArea->text, textArea->obj.area.width, textArea->wrapping); - textArea->obj.alignment = BOTTOM_MIDDLE; - textArea->obj.alignTo = (nbgl_obj_t*)container->children[container->nbChildren-1]; - textArea->obj.alignmentMarginY = 40; + container = (nbgl_container_t *) nbgl_objPoolGet(CONTAINER, layoutInt->layer); - fullHeight += textArea->obj.area.height; + // get container children (max 2 (QRCode + text1/text2)) + container->children = nbgl_containerPoolGet(2, layoutInt->layer); + container->nbChildren = 0; - container->children[container->nbChildren] = (nbgl_obj_t*)textArea; + qrcode = (nbgl_qrcode_t *) nbgl_objPoolGet(QR_CODE, layoutInt->layer); + // version is forced to V10 if url is longer than 62 characters + if (strlen(PIC(info->url)) > 62) { + qrcode->version = QRCODE_V10; + } + else { + qrcode->version = QRCODE_V4; + } + qrcode->foregroundColor = BLACK; + // in QR V4, we use 8*8 screen pixels for one QR pixel + // in QR V10, we use 4*4 screen pixels for one QR pixel + qrcode->obj.area.width + = (qrcode->version == QRCODE_V4) ? (QR_V4_NB_PIX_SIZE * 8) : (QR_V10_NB_PIX_SIZE * 4); + qrcode->obj.area.height = qrcode->obj.area.width; + qrcode->text = PIC(info->url); + qrcode->obj.area.bpp = NBGL_BPP_1; + qrcode->obj.alignment = TOP_MIDDLE; + qrcode->obj.alignmentMarginY = 24; + + fullHeight += qrcode->obj.area.height; + container->children[container->nbChildren] = (nbgl_obj_t *) qrcode; container->nbChildren++; - } - container->obj.area.height = fullHeight; - container->layout = VERTICAL; - // center the QRCode only if it's the first (and probably only) child - if (layoutInt->container->nbChildren == 0) { - container->obj.alignment = CENTER; - } - else { - container->obj.alignment = BOTTOM_MIDDLE; - container->obj.alignmentMarginY = BORDER_MARGIN; - container->obj.alignTo = layoutInt->container->children[layoutInt->container->nbChildren-1]; - } - container->obj.area.width = AVAILABLE_WIDTH; + if (info->text1 != NULL) { + textArea = (nbgl_text_area_t *) nbgl_objPoolGet(TEXT_AREA, layoutInt->layer); + textArea->textColor = BLACK; + textArea->text = PIC(info->text1); + textArea->textAlignment = CENTER; + textArea->fontId = (info->largeText1 == true) ? BAGL_FONT_INTER_MEDIUM_32px + : BAGL_FONT_INTER_REGULAR_24px; + textArea->wrapping = true; + textArea->obj.area.width = AVAILABLE_WIDTH; + textArea->obj.area.height = nbgl_getTextHeightInWidth( + textArea->fontId, textArea->text, textArea->obj.area.width, textArea->wrapping); + textArea->obj.alignment = BOTTOM_MIDDLE; + textArea->obj.alignTo = (nbgl_obj_t *) container->children[container->nbChildren - 1]; + textArea->obj.alignmentMarginY = 40; + + fullHeight += textArea->obj.area.height; + + container->children[container->nbChildren] = (nbgl_obj_t *) textArea; + container->nbChildren++; + } + else if (info->text2 != NULL) { + textArea = (nbgl_text_area_t *) nbgl_objPoolGet(TEXT_AREA, layoutInt->layer); + textArea->textColor = DARK_GRAY; + textArea->text = PIC(info->text2); + textArea->textAlignment = CENTER; + textArea->fontId = BAGL_FONT_INTER_REGULAR_24px; + textArea->wrapping = true; + textArea->obj.area.width = AVAILABLE_WIDTH; + textArea->obj.area.height = nbgl_getTextHeightInWidth( + textArea->fontId, textArea->text, textArea->obj.area.width, textArea->wrapping); + textArea->obj.alignment = BOTTOM_MIDDLE; + textArea->obj.alignTo = (nbgl_obj_t *) container->children[container->nbChildren - 1]; + textArea->obj.alignmentMarginY = 40; + + fullHeight += textArea->obj.area.height; + + container->children[container->nbChildren] = (nbgl_obj_t *) textArea; + container->nbChildren++; + } + container->obj.area.height = fullHeight; + container->layout = VERTICAL; + // center the QRCode only if it's the first (and probably only) child + if (layoutInt->container->nbChildren == 0) { + container->obj.alignment = CENTER; + } + else { + container->obj.alignment = BOTTOM_MIDDLE; + container->obj.alignmentMarginY = BORDER_MARGIN; + container->obj.alignTo + = layoutInt->container->children[layoutInt->container->nbChildren - 1]; + } + + container->obj.area.width = AVAILABLE_WIDTH; - // set this new container as child of main container - addObjectToLayout(layoutInt,(nbgl_obj_t*)container); + // set this new container as child of main container + addObjectToLayout(layoutInt, (nbgl_obj_t *) container); - return 0; + return 0; } -#endif // NBGL_QRCODE +#endif // NBGL_QRCODE /** * @brief Creates two buttons to make a choice. Both buttons are mandatory @@ -1315,74 +1432,79 @@ int nbgl_layoutAddQRCode(nbgl_layout_t *layout, const nbgl_layoutQRCode_t *info) * @param info structure giving the description of buttons (texts, icons, layout) * @return >= 0 if OK */ -int nbgl_layoutAddChoiceButtons(nbgl_layout_t *layout, const nbgl_layoutChoiceButtons_t *info) { - layoutObj_t *obj; - nbgl_button_t *topButton, *bottomButton; - nbgl_layoutInternal_t *layoutInt = (nbgl_layoutInternal_t *)layout; - - LOG_DEBUG(LAYOUT_LOGGER,"nbgl_layoutAddChoiceButtons():\n"); - if (layout == NULL) - return -1; - - // texts cannot be NULL - if ((info->bottomText == NULL) || (info->topText == NULL)) - return -1; - - // create bottomButton (in white) at first - bottomButton = (nbgl_button_t *)nbgl_objPoolGet(BUTTON,layoutInt->layer); - obj = addCallbackObj(layoutInt,(nbgl_obj_t*)bottomButton,info->token,info->tuneId); - if (obj == NULL) - return -1; - // associate with with index 1 - obj->index = 1; - bottomButton->obj.alignment = BOTTOM_MIDDLE; - if (info->style == ROUNDED_AND_FOOTER_STYLE) { - bottomButton->obj.alignmentMarginY = 4; // 4 pixels from screen bottom - bottomButton->borderColor = WHITE; - } - else if (info->style == BOTH_ROUNDED_STYLE) { - bottomButton->obj.alignmentMarginY = BORDER_MARGIN; // 24 pixels from screen bottom - bottomButton->borderColor = LIGHT_GRAY; - } - bottomButton->innerColor = WHITE; - bottomButton->foregroundColor = BLACK; - bottomButton->obj.area.width = AVAILABLE_WIDTH; - bottomButton->obj.area.height = BUTTON_DIAMETER; - bottomButton->radius = BUTTON_RADIUS; - bottomButton->text = PIC(info->bottomText); - bottomButton->fontId = BAGL_FONT_INTER_SEMIBOLD_24px; - bottomButton->obj.touchMask = (1 << TOUCHED); - // set this new button as child of the container - addObjectToLayout(layoutInt,(nbgl_obj_t*)bottomButton); - - // then black button, on top of it - topButton = (nbgl_button_t *)nbgl_objPoolGet(BUTTON,layoutInt->layer); - obj = addCallbackObj(layoutInt,(nbgl_obj_t*)topButton,info->token,info->tuneId); - if (obj == NULL) - return -1; - // associate with with index 0 - obj->index = 0; - topButton->obj.alignment = TOP_MIDDLE; - topButton->obj.alignTo = (nbgl_obj_t*)bottomButton; - if (info->style == BOTH_ROUNDED_STYLE) { - topButton->obj.alignmentMarginY = INNER_MARGIN; // 12 pixels from bottom button - } - else { - topButton->obj.alignmentMarginY = 4; // 4 pixels from bottom button - } - topButton->innerColor = BLACK; - topButton->borderColor = BLACK; - topButton->foregroundColor = WHITE; - topButton->obj.area.width = bottomButton->obj.area.width; - topButton->obj.area.height = BUTTON_DIAMETER; - topButton->radius = BUTTON_RADIUS; - topButton->text = PIC(info->topText); - topButton->fontId = BAGL_FONT_INTER_SEMIBOLD_24px; - topButton->obj.touchMask = (1 << TOUCHED); - // set this new button as child of the container - addObjectToLayout(layoutInt,(nbgl_obj_t*)topButton); - - return 0; +int nbgl_layoutAddChoiceButtons(nbgl_layout_t *layout, const nbgl_layoutChoiceButtons_t *info) +{ + layoutObj_t *obj; + nbgl_button_t *topButton, *bottomButton; + nbgl_layoutInternal_t *layoutInt = (nbgl_layoutInternal_t *) layout; + + LOG_DEBUG(LAYOUT_LOGGER, "nbgl_layoutAddChoiceButtons():\n"); + if (layout == NULL) { + return -1; + } + + // texts cannot be NULL + if ((info->bottomText == NULL) || (info->topText == NULL)) { + return -1; + } + + // create bottomButton (in white) at first + bottomButton = (nbgl_button_t *) nbgl_objPoolGet(BUTTON, layoutInt->layer); + obj = addCallbackObj(layoutInt, (nbgl_obj_t *) bottomButton, info->token, info->tuneId); + if (obj == NULL) { + return -1; + } + // associate with with index 1 + obj->index = 1; + bottomButton->obj.alignment = BOTTOM_MIDDLE; + if (info->style == ROUNDED_AND_FOOTER_STYLE) { + bottomButton->obj.alignmentMarginY = 4; // 4 pixels from screen bottom + bottomButton->borderColor = WHITE; + } + else if (info->style == BOTH_ROUNDED_STYLE) { + bottomButton->obj.alignmentMarginY = BORDER_MARGIN; // 24 pixels from screen bottom + bottomButton->borderColor = LIGHT_GRAY; + } + bottomButton->innerColor = WHITE; + bottomButton->foregroundColor = BLACK; + bottomButton->obj.area.width = AVAILABLE_WIDTH; + bottomButton->obj.area.height = BUTTON_DIAMETER; + bottomButton->radius = BUTTON_RADIUS; + bottomButton->text = PIC(info->bottomText); + bottomButton->fontId = BAGL_FONT_INTER_SEMIBOLD_24px; + bottomButton->obj.touchMask = (1 << TOUCHED); + // set this new button as child of the container + addObjectToLayout(layoutInt, (nbgl_obj_t *) bottomButton); + + // then black button, on top of it + topButton = (nbgl_button_t *) nbgl_objPoolGet(BUTTON, layoutInt->layer); + obj = addCallbackObj(layoutInt, (nbgl_obj_t *) topButton, info->token, info->tuneId); + if (obj == NULL) { + return -1; + } + // associate with with index 0 + obj->index = 0; + topButton->obj.alignment = TOP_MIDDLE; + topButton->obj.alignTo = (nbgl_obj_t *) bottomButton; + if (info->style == BOTH_ROUNDED_STYLE) { + topButton->obj.alignmentMarginY = INNER_MARGIN; // 12 pixels from bottom button + } + else { + topButton->obj.alignmentMarginY = 4; // 4 pixels from bottom button + } + topButton->innerColor = BLACK; + topButton->borderColor = BLACK; + topButton->foregroundColor = WHITE; + topButton->obj.area.width = bottomButton->obj.area.width; + topButton->obj.area.height = BUTTON_DIAMETER; + topButton->radius = BUTTON_RADIUS; + topButton->text = PIC(info->topText); + topButton->fontId = BAGL_FONT_INTER_SEMIBOLD_24px; + topButton->obj.touchMask = (1 << TOUCHED); + // set this new button as child of the container + addObjectToLayout(layoutInt, (nbgl_obj_t *) topButton); + + return 0; } /** @@ -1392,182 +1514,199 @@ int nbgl_layoutAddChoiceButtons(nbgl_layout_t *layout, const nbgl_layoutChoiceBu * @param list structure giving the list of [tag,value] pairs * @return >= 0 if OK */ -int nbgl_layoutAddTagValueList(nbgl_layout_t *layout, const nbgl_layoutTagValueList_t *list) { - nbgl_layoutInternal_t *layoutInt = (nbgl_layoutInternal_t *)layout; - nbgl_text_area_t *itemTextArea; - nbgl_text_area_t *valueTextArea; - nbgl_container_t *container; - uint8_t i; - - LOG_DEBUG(LAYOUT_LOGGER,"nbgl_layoutAddTagValueList():\n"); - if (layout == NULL) - return -1; - - for (i=0;inbPairs;i++) { - nbgl_layoutTagValue_t *pair; - uint16_t fullHeight = 0, usableWidth; - - if (list->pairs != NULL) { - pair = &list->pairs[i]; +int nbgl_layoutAddTagValueList(nbgl_layout_t *layout, const nbgl_layoutTagValueList_t *list) +{ + nbgl_layoutInternal_t *layoutInt = (nbgl_layoutInternal_t *) layout; + nbgl_text_area_t *itemTextArea; + nbgl_text_area_t *valueTextArea; + nbgl_container_t *container; + uint8_t i; + + LOG_DEBUG(LAYOUT_LOGGER, "nbgl_layoutAddTagValueList():\n"); + if (layout == NULL) { + return -1; } - else { - pair = list->callback(list->startIndex+i); - } - // width that can be used for item and text - usableWidth = AVAILABLE_WIDTH; - - container = (nbgl_container_t *)nbgl_objPoolGet(CONTAINER,layoutInt->layer); - - // get container children (max 3 if a valueIcon, otherwise 2) - container->children = nbgl_containerPoolGet((pair->valueIcon != NULL)?3:2,layoutInt->layer); - - itemTextArea = (nbgl_text_area_t *)nbgl_objPoolGet(TEXT_AREA,layoutInt->layer); - valueTextArea = (nbgl_text_area_t *)nbgl_objPoolGet(TEXT_AREA,layoutInt->layer); - - // init text area for this choice - itemTextArea->textColor = DARK_GRAY; - itemTextArea->text = PIC(pair->item); - itemTextArea->textAlignment = MID_LEFT; - itemTextArea->fontId = BAGL_FONT_INTER_REGULAR_24px; - itemTextArea->wrapping = true; - itemTextArea->obj.area.width = usableWidth; - itemTextArea->obj.area.height = nbgl_getTextHeightInWidth(itemTextArea->fontId, itemTextArea->text, usableWidth, itemTextArea->wrapping); - itemTextArea->style = NO_STYLE; - itemTextArea->obj.alignment = NO_ALIGNMENT; - itemTextArea->obj.alignmentMarginX = 0; - itemTextArea->obj.alignmentMarginY = 0; - itemTextArea->obj.alignTo = NULL; - container->children[container->nbChildren] = (nbgl_obj_t*)itemTextArea; - container->nbChildren++; - fullHeight += itemTextArea->obj.area.height; + for (i = 0; i < list->nbPairs; i++) { + nbgl_layoutTagValue_t *pair; + uint16_t fullHeight = 0, usableWidth; - // init button for this choice - valueTextArea->textColor = BLACK; - valueTextArea->text = PIC(pair->value); - valueTextArea->textAlignment = MID_LEFT; - if (list->smallCaseForValue) { - valueTextArea->fontId = BAGL_FONT_INTER_REGULAR_24px; - } else { - valueTextArea->fontId = BAGL_FONT_INTER_MEDIUM_32px; - } - if (pair->valueIcon == NULL) { - valueTextArea->obj.area.width = usableWidth; - } - else { - // we assume that value is single line - valueTextArea->obj.area.width = nbgl_getTextWidth(valueTextArea->fontId, valueTextArea->text); - } - - // handle the nbMaxLinesForValue parameter, used to automatically keep only - // nbMaxLinesForValue lines - uint16_t nbLines = nbgl_getTextNbLinesInWidth(valueTextArea->fontId,valueTextArea->text,usableWidth,list->wrapping); - // use this nbMaxLinesForValue parameter only if >0 - if ((list->nbMaxLinesForValue > 0) && (nbLines > list->nbMaxLinesForValue)) { - nbLines = list->nbMaxLinesForValue; - valueTextArea->nbMaxLines = list->nbMaxLinesForValue; - } - const nbgl_font_t *font = nbgl_getFont(valueTextArea->fontId); - valueTextArea->obj.area.height = nbLines*font->line_height; - valueTextArea->style = NO_STYLE; - valueTextArea->obj.alignment = BOTTOM_LEFT; - valueTextArea->obj.alignmentMarginY = 4; - valueTextArea->obj.alignTo = (nbgl_obj_t*)itemTextArea; - valueTextArea->wrapping = list->wrapping; - container->children[container->nbChildren] = (nbgl_obj_t*)valueTextArea; - container->nbChildren++; - - fullHeight += valueTextArea->obj.area.height; - if (pair->valueIcon != NULL) { - nbgl_image_t *image = (nbgl_image_t *)nbgl_objPoolGet(IMAGE,layoutInt->layer); - layoutObj_t *obj = addCallbackObj(layoutInt,(nbgl_obj_t*)image,list->token,TUNE_TAP_CASUAL); - obj->index = i; - image->foregroundColor = BLACK; - image->buffer = PIC(pair->valueIcon); - image->obj.alignment = MID_RIGHT; - image->obj.alignmentMarginX = 4; - image->obj.alignTo = (nbgl_obj_t*)valueTextArea; - image->obj.touchMask = (1 << TOUCHED); + if (list->pairs != NULL) { + pair = &list->pairs[i]; + } + else { + pair = list->callback(list->startIndex + i); + } + // width that can be used for item and text + usableWidth = AVAILABLE_WIDTH; + + container = (nbgl_container_t *) nbgl_objPoolGet(CONTAINER, layoutInt->layer); + + // get container children (max 3 if a valueIcon, otherwise 2) + container->children + = nbgl_containerPoolGet((pair->valueIcon != NULL) ? 3 : 2, layoutInt->layer); + + itemTextArea = (nbgl_text_area_t *) nbgl_objPoolGet(TEXT_AREA, layoutInt->layer); + valueTextArea = (nbgl_text_area_t *) nbgl_objPoolGet(TEXT_AREA, layoutInt->layer); + + // init text area for this choice + itemTextArea->textColor = DARK_GRAY; + itemTextArea->text = PIC(pair->item); + itemTextArea->textAlignment = MID_LEFT; + itemTextArea->fontId = BAGL_FONT_INTER_REGULAR_24px; + itemTextArea->wrapping = true; + itemTextArea->obj.area.width = usableWidth; + itemTextArea->obj.area.height = nbgl_getTextHeightInWidth( + itemTextArea->fontId, itemTextArea->text, usableWidth, itemTextArea->wrapping); + itemTextArea->style = NO_STYLE; + itemTextArea->obj.alignment = NO_ALIGNMENT; + itemTextArea->obj.alignmentMarginX = 0; + itemTextArea->obj.alignmentMarginY = 0; + itemTextArea->obj.alignTo = NULL; + container->children[container->nbChildren] = (nbgl_obj_t *) itemTextArea; + container->nbChildren++; + + fullHeight += itemTextArea->obj.area.height; + + // init button for this choice + valueTextArea->textColor = BLACK; + valueTextArea->text = PIC(pair->value); + valueTextArea->textAlignment = MID_LEFT; + if (list->smallCaseForValue) { + valueTextArea->fontId = BAGL_FONT_INTER_REGULAR_24px; + } + else { + valueTextArea->fontId = BAGL_FONT_INTER_MEDIUM_32px; + } + if (pair->valueIcon == NULL) { + valueTextArea->obj.area.width = usableWidth; + } + else { + // we assume that value is single line + valueTextArea->obj.area.width + = nbgl_getTextWidth(valueTextArea->fontId, valueTextArea->text); + } - container->children[container->nbChildren] = (nbgl_obj_t*)image; - container->nbChildren++; - } + // handle the nbMaxLinesForValue parameter, used to automatically keep only + // nbMaxLinesForValue lines + uint16_t nbLines = nbgl_getTextNbLinesInWidth( + valueTextArea->fontId, valueTextArea->text, usableWidth, list->wrapping); + // use this nbMaxLinesForValue parameter only if >0 + if ((list->nbMaxLinesForValue > 0) && (nbLines > list->nbMaxLinesForValue)) { + nbLines = list->nbMaxLinesForValue; + valueTextArea->nbMaxLines = list->nbMaxLinesForValue; + } + const nbgl_font_t *font = nbgl_getFont(valueTextArea->fontId); + valueTextArea->obj.area.height = nbLines * font->line_height; + valueTextArea->style = NO_STYLE; + valueTextArea->obj.alignment = BOTTOM_LEFT; + valueTextArea->obj.alignmentMarginY = 4; + valueTextArea->obj.alignTo = (nbgl_obj_t *) itemTextArea; + valueTextArea->wrapping = list->wrapping; + container->children[container->nbChildren] = (nbgl_obj_t *) valueTextArea; + container->nbChildren++; + + fullHeight += valueTextArea->obj.area.height; + if (pair->valueIcon != NULL) { + nbgl_image_t *image = (nbgl_image_t *) nbgl_objPoolGet(IMAGE, layoutInt->layer); + layoutObj_t *obj + = addCallbackObj(layoutInt, (nbgl_obj_t *) image, list->token, TUNE_TAP_CASUAL); + obj->index = i; + image->foregroundColor = BLACK; + image->buffer = PIC(pair->valueIcon); + image->obj.alignment = MID_RIGHT; + image->obj.alignmentMarginX = 4; + image->obj.alignTo = (nbgl_obj_t *) valueTextArea; + image->obj.touchMask = (1 << TOUCHED); + + container->children[container->nbChildren] = (nbgl_obj_t *) image; + container->nbChildren++; + } - container->obj.area.width = usableWidth; - container->obj.area.height = fullHeight; - container->layout = VERTICAL; - container->obj.alignmentMarginX = BORDER_MARGIN; - container->obj.alignmentMarginY = 12; - container->obj.alignment = NO_ALIGNMENT; + container->obj.area.width = usableWidth; + container->obj.area.height = fullHeight; + container->layout = VERTICAL; + container->obj.alignmentMarginX = BORDER_MARGIN; + container->obj.alignmentMarginY = 12; + container->obj.alignment = NO_ALIGNMENT; - addObjectToLayout(layoutInt,(nbgl_obj_t*)container); - } + addObjectToLayout(layoutInt, (nbgl_obj_t *) container); + } - return 0; + return 0; } /** - * @brief Creates an area in main panel to display a progress bar, with a title text and a description under the progress + * @brief Creates an area in main panel to display a progress bar, with a title text and a + * description under the progress * * @param layout the current layout * @param barLayout structure giving the description of progress bar * @return >= 0 if OK */ -int nbgl_layoutAddProgressBar(nbgl_layout_t *layout, const nbgl_layoutProgressBar_t *barLayout) { - nbgl_layoutInternal_t *layoutInt = (nbgl_layoutInternal_t *)layout; - nbgl_progress_bar_t *progress; - - LOG_DEBUG(LAYOUT_LOGGER,"nbgl_layoutAddProgressBar():\n"); - if (layout == NULL) - return -1; - if (barLayout->text != NULL) { - nbgl_text_area_t *textArea; - - textArea = (nbgl_text_area_t *)nbgl_objPoolGet(TEXT_AREA,((nbgl_layoutInternal_t *)layout)->layer); - textArea->textColor=BLACK; - textArea->text = PIC(barLayout->text); - textArea->textAlignment = MID_LEFT; - textArea->fontId = BAGL_FONT_INTER_REGULAR_24px; - textArea->wrapping = true; - textArea->obj.area.width = AVAILABLE_WIDTH; - textArea->obj.area.height = nbgl_getTextHeightInWidth(textArea->fontId, textArea->text, textArea->obj.area.width, textArea->wrapping); - textArea->style = NO_STYLE; - textArea->obj.alignment = NO_ALIGNMENT; - textArea->obj.alignmentMarginX = BORDER_MARGIN; - textArea->obj.alignmentMarginY = BORDER_MARGIN; - addObjectToLayout(layoutInt,(nbgl_obj_t*)textArea); - } - progress = (nbgl_progress_bar_t *)nbgl_objPoolGet(PROGRESS_BAR,((nbgl_layoutInternal_t *)layout)->layer); - progress->foregroundColor = BLACK; - progress->withBorder = true; - progress->state = barLayout->percentage; - progress->obj.area.width = 120; - progress->obj.area.height = 12; - progress->obj.alignment = NO_ALIGNMENT; - progress->obj.alignmentMarginX = (AVAILABLE_WIDTH-progress->obj.area.width)/2; - progress->obj.alignmentMarginY = BORDER_MARGIN; - addObjectToLayout(layoutInt,(nbgl_obj_t*)progress); - - if (barLayout->subText != NULL) { - nbgl_text_area_t *subTextArea; - - subTextArea = (nbgl_text_area_t *)nbgl_objPoolGet(TEXT_AREA,((nbgl_layoutInternal_t *)layout)->layer); - subTextArea->textColor=LIGHT_GRAY; - subTextArea->text = PIC(barLayout->subText); - subTextArea->textAlignment = MID_LEFT; - subTextArea->fontId = BAGL_FONT_INTER_REGULAR_24px; - subTextArea->wrapping = true; - subTextArea->obj.area.width = AVAILABLE_WIDTH; - subTextArea->obj.area.height = nbgl_getTextHeightInWidth(subTextArea->fontId, subTextArea->text, subTextArea->obj.area.width, subTextArea->wrapping); - subTextArea->style = NO_STYLE; - subTextArea->obj.alignment = NO_ALIGNMENT; - subTextArea->obj.alignmentMarginX = BORDER_MARGIN; - subTextArea->obj.alignmentMarginY = BORDER_MARGIN; - addObjectToLayout(layoutInt,(nbgl_obj_t*)subTextArea); - } - - return 0; +int nbgl_layoutAddProgressBar(nbgl_layout_t *layout, const nbgl_layoutProgressBar_t *barLayout) +{ + nbgl_layoutInternal_t *layoutInt = (nbgl_layoutInternal_t *) layout; + nbgl_progress_bar_t *progress; + + LOG_DEBUG(LAYOUT_LOGGER, "nbgl_layoutAddProgressBar():\n"); + if (layout == NULL) { + return -1; + } + if (barLayout->text != NULL) { + nbgl_text_area_t *textArea; + + textArea = (nbgl_text_area_t *) nbgl_objPoolGet(TEXT_AREA, + ((nbgl_layoutInternal_t *) layout)->layer); + textArea->textColor = BLACK; + textArea->text = PIC(barLayout->text); + textArea->textAlignment = MID_LEFT; + textArea->fontId = BAGL_FONT_INTER_REGULAR_24px; + textArea->wrapping = true; + textArea->obj.area.width = AVAILABLE_WIDTH; + textArea->obj.area.height = nbgl_getTextHeightInWidth( + textArea->fontId, textArea->text, textArea->obj.area.width, textArea->wrapping); + textArea->style = NO_STYLE; + textArea->obj.alignment = NO_ALIGNMENT; + textArea->obj.alignmentMarginX = BORDER_MARGIN; + textArea->obj.alignmentMarginY = BORDER_MARGIN; + addObjectToLayout(layoutInt, (nbgl_obj_t *) textArea); + } + progress = (nbgl_progress_bar_t *) nbgl_objPoolGet(PROGRESS_BAR, + ((nbgl_layoutInternal_t *) layout)->layer); + progress->foregroundColor = BLACK; + progress->withBorder = true; + progress->state = barLayout->percentage; + progress->obj.area.width = 120; + progress->obj.area.height = 12; + progress->obj.alignment = NO_ALIGNMENT; + progress->obj.alignmentMarginX = (AVAILABLE_WIDTH - progress->obj.area.width) / 2; + progress->obj.alignmentMarginY = BORDER_MARGIN; + addObjectToLayout(layoutInt, (nbgl_obj_t *) progress); + + if (barLayout->subText != NULL) { + nbgl_text_area_t *subTextArea; + + subTextArea = (nbgl_text_area_t *) nbgl_objPoolGet( + TEXT_AREA, ((nbgl_layoutInternal_t *) layout)->layer); + subTextArea->textColor = LIGHT_GRAY; + subTextArea->text = PIC(barLayout->subText); + subTextArea->textAlignment = MID_LEFT; + subTextArea->fontId = BAGL_FONT_INTER_REGULAR_24px; + subTextArea->wrapping = true; + subTextArea->obj.area.width = AVAILABLE_WIDTH; + subTextArea->obj.area.height = nbgl_getTextHeightInWidth(subTextArea->fontId, + subTextArea->text, + subTextArea->obj.area.width, + subTextArea->wrapping); + subTextArea->style = NO_STYLE; + subTextArea->obj.alignment = NO_ALIGNMENT; + subTextArea->obj.alignmentMarginX = BORDER_MARGIN; + subTextArea->obj.alignmentMarginY = BORDER_MARGIN; + addObjectToLayout(layoutInt, (nbgl_obj_t *) subTextArea); + } + return 0; } /** @@ -1576,15 +1715,16 @@ int nbgl_layoutAddProgressBar(nbgl_layout_t *layout, const nbgl_layoutProgressBa * @param layout the current layout * @return >= 0 if OK */ -int nbgl_layoutAddSeparationLine(nbgl_layout_t *layout) { - nbgl_layoutInternal_t *layoutInt = (nbgl_layoutInternal_t *)layout; - nbgl_line_t *line; - - LOG_DEBUG(LAYOUT_LOGGER,"nbgl_layoutAddSeparationLine():\n"); - line = createHorizontalLine(layoutInt->layer); - line->obj.alignmentMarginY = -4; - addObjectToLayout(layoutInt,(nbgl_obj_t*)line); - return 0; +int nbgl_layoutAddSeparationLine(nbgl_layout_t *layout) +{ + nbgl_layoutInternal_t *layoutInt = (nbgl_layoutInternal_t *) layout; + nbgl_line_t *line; + + LOG_DEBUG(LAYOUT_LOGGER, "nbgl_layoutAddSeparationLine():\n"); + line = createHorizontalLine(layoutInt->layer); + line->obj.alignmentMarginY = -4; + addObjectToLayout(layoutInt, (nbgl_obj_t *) line); + return 0; } /** @@ -1594,68 +1734,74 @@ int nbgl_layoutAddSeparationLine(nbgl_layout_t *layout) { * @param buttonInfo structure giving the description of button (text, icon, layout) * @return >= 0 if OK */ -int nbgl_layoutAddButton(nbgl_layout_t *layout, const nbgl_layoutButton_t *buttonInfo) { - layoutObj_t *obj; - nbgl_button_t *button; - nbgl_layoutInternal_t *layoutInt = (nbgl_layoutInternal_t *)layout; - - LOG_DEBUG(LAYOUT_LOGGER,"nbgl_layoutAddButton():\n"); - if (layout == NULL) - return -1; - - button = (nbgl_button_t *)nbgl_objPoolGet(BUTTON,layoutInt->layer); - obj = addCallbackObj(layoutInt,(nbgl_obj_t*)button,buttonInfo->token,buttonInfo->tuneId); - if (obj == NULL) - return -1; - - button->obj.alignmentMarginY = BORDER_MARGIN; - if (buttonInfo->onBottom != true) { - button->obj.alignmentMarginX = BORDER_MARGIN; - button->obj.alignment = NO_ALIGNMENT; - } - else { - button->obj.alignment = BOTTOM_MIDDLE; - } - if (buttonInfo->style == BLACK_BACKGROUND) { - button->innerColor = BLACK; - button->foregroundColor = WHITE; - } - else { - button->innerColor = WHITE; - button->foregroundColor = BLACK; - } - if (buttonInfo->style == NO_BORDER) { - button->borderColor = WHITE; - } - else { +int nbgl_layoutAddButton(nbgl_layout_t *layout, const nbgl_layoutButton_t *buttonInfo) +{ + layoutObj_t *obj; + nbgl_button_t *button; + nbgl_layoutInternal_t *layoutInt = (nbgl_layoutInternal_t *) layout; + + LOG_DEBUG(LAYOUT_LOGGER, "nbgl_layoutAddButton():\n"); + if (layout == NULL) { + return -1; + } + + button = (nbgl_button_t *) nbgl_objPoolGet(BUTTON, layoutInt->layer); + obj = addCallbackObj(layoutInt, (nbgl_obj_t *) button, buttonInfo->token, buttonInfo->tuneId); + if (obj == NULL) { + return -1; + } + + button->obj.alignmentMarginY = BORDER_MARGIN; + if (buttonInfo->onBottom != true) { + button->obj.alignmentMarginX = BORDER_MARGIN; + button->obj.alignment = NO_ALIGNMENT; + } + else { + button->obj.alignment = BOTTOM_MIDDLE; + } if (buttonInfo->style == BLACK_BACKGROUND) { - button->borderColor = BLACK; + button->innerColor = BLACK; + button->foregroundColor = WHITE; } else { - button->borderColor = LIGHT_GRAY; - } - } - button->text = PIC(buttonInfo->text); - button->fontId = BAGL_FONT_INTER_SEMIBOLD_24px; - button->icon = PIC(buttonInfo->icon); - if (buttonInfo->fittingContent == true) { - button->obj.area.width = nbgl_getTextWidth(button->fontId,button->text)+64+((button->icon)?(button->icon->width+8):0); - button->obj.area.height = 64; - button->radius = RADIUS_32_PIXELS; - if (buttonInfo->onBottom != true) - button->obj.alignmentMarginX += (SCREEN_WIDTH-2*BORDER_MARGIN-button->obj.area.width)/2; - } - else { - button->obj.area.width = AVAILABLE_WIDTH; - button->obj.area.height = BUTTON_DIAMETER; - button->radius = BUTTON_RADIUS; - } - button->obj.alignTo = NULL; - button->obj.touchMask = (1 << TOUCHED); - // set this new button as child of the container - addObjectToLayout(layoutInt,(nbgl_obj_t*)button); - - return 0; + button->innerColor = WHITE; + button->foregroundColor = BLACK; + } + if (buttonInfo->style == NO_BORDER) { + button->borderColor = WHITE; + } + else { + if (buttonInfo->style == BLACK_BACKGROUND) { + button->borderColor = BLACK; + } + else { + button->borderColor = LIGHT_GRAY; + } + } + button->text = PIC(buttonInfo->text); + button->fontId = BAGL_FONT_INTER_SEMIBOLD_24px; + button->icon = PIC(buttonInfo->icon); + if (buttonInfo->fittingContent == true) { + button->obj.area.width = nbgl_getTextWidth(button->fontId, button->text) + 64 + + ((button->icon) ? (button->icon->width + 8) : 0); + button->obj.area.height = 64; + button->radius = RADIUS_32_PIXELS; + if (buttonInfo->onBottom != true) { + button->obj.alignmentMarginX + += (SCREEN_WIDTH - 2 * BORDER_MARGIN - button->obj.area.width) / 2; + } + } + else { + button->obj.area.width = AVAILABLE_WIDTH; + button->obj.area.height = BUTTON_DIAMETER; + button->radius = BUTTON_RADIUS; + } + button->obj.alignTo = NULL; + button->obj.touchMask = (1 << TOUCHED); + // set this new button as child of the container + addObjectToLayout(layoutInt, (nbgl_obj_t *) button); + + return 0; } /** @@ -1667,79 +1813,89 @@ int nbgl_layoutAddButton(nbgl_layout_t *layout, const nbgl_layoutButton_t *butto * @param tuneId if not @ref NBGL_NO_TUNE, a tune will be played when button is long pressed * @return >= 0 if OK */ -int nbgl_layoutAddLongPressButton(nbgl_layout_t *layout, const char *text, uint8_t token, tune_index_e tuneId) { - layoutObj_t *obj; - nbgl_button_t *button; - nbgl_text_area_t *textArea; - nbgl_progress_bar_t *progressBar; - nbgl_container_t *container; - nbgl_layoutInternal_t *layoutInt = (nbgl_layoutInternal_t *)layout; - nbgl_line_t *line; - - LOG_DEBUG(LAYOUT_LOGGER,"nbgl_layoutAddLongPressButton():\n"); - if (layout == NULL) - return -1; - - container = (nbgl_container_t *)nbgl_objPoolGet(CONTAINER, layoutInt->layer); - obj = addCallbackObj(layoutInt,(nbgl_obj_t*)container,token,tuneId); - if (obj == NULL) - return -1; - - container->obj.area.width = SCREEN_WIDTH; - container->obj.area.height = 128; - container->layout = VERTICAL ; - container->nbChildren = 4; // progress-bar + text + line + button - container->children = (nbgl_obj_t**)nbgl_containerPoolGet(container->nbChildren,layoutInt->layer); - container->obj.alignment = BOTTOM_MIDDLE; - container->obj.touchMask = ((1<layer); - button->obj.alignmentMarginX = BORDER_MARGIN; - button->obj.alignment = MID_RIGHT; - button->innerColor = BLACK; - button->foregroundColor = WHITE; - button->borderColor = BLACK; - button->obj.area.width = BUTTON_DIAMETER; - button->obj.area.height = BUTTON_DIAMETER; - button->radius = BUTTON_RADIUS; - button->icon = PIC(&C_check32px); - container->children[0] = (nbgl_obj_t*)button; - - textArea = (nbgl_text_area_t *)nbgl_objPoolGet(TEXT_AREA,layoutInt->layer); - textArea->textColor = BLACK; - textArea->text = PIC(text); - textArea->textAlignment = MID_LEFT; - textArea->fontId = BAGL_FONT_INTER_MEDIUM_32px; - textArea->wrapping = true; - textArea->obj.area.width = container->obj.area.width - 3 * BORDER_MARGIN - button->obj.area.width; - textArea->obj.area.height = nbgl_getTextHeightInWidth(textArea->fontId, textArea->text, textArea->obj.area.width, textArea->wrapping); - textArea->style = NO_STYLE; - textArea->obj.alignment = MID_LEFT; - textArea->obj.alignmentMarginX = BORDER_MARGIN; - container->children[1] = (nbgl_obj_t*)textArea; - - line = createHorizontalLine(layoutInt->layer); - line->offset = 3; - line->obj.alignment = TOP_MIDDLE; - container->children[2] = (nbgl_obj_t*)line; - - progressBar = (nbgl_progress_bar_t *)nbgl_objPoolGet(PROGRESS_BAR,layoutInt->layer); - progressBar->withBorder = false; - progressBar->obj.area.width = container->obj.area.width; - progressBar->obj.area.height = 8; - progressBar->obj.alignment = TOP_MIDDLE; - progressBar->obj.alignmentMarginY = 4; - progressBar->obj.alignTo = NULL; - container->children[3] = (nbgl_obj_t*)progressBar; - - // set this new container as child of the main container - addObjectToLayout(layoutInt,(nbgl_obj_t*)container); - - return 0; +int nbgl_layoutAddLongPressButton(nbgl_layout_t *layout, + const char *text, + uint8_t token, + tune_index_e tuneId) +{ + layoutObj_t *obj; + nbgl_button_t *button; + nbgl_text_area_t *textArea; + nbgl_progress_bar_t *progressBar; + nbgl_container_t *container; + nbgl_layoutInternal_t *layoutInt = (nbgl_layoutInternal_t *) layout; + nbgl_line_t *line; + + LOG_DEBUG(LAYOUT_LOGGER, "nbgl_layoutAddLongPressButton():\n"); + if (layout == NULL) { + return -1; + } + + container = (nbgl_container_t *) nbgl_objPoolGet(CONTAINER, layoutInt->layer); + obj = addCallbackObj(layoutInt, (nbgl_obj_t *) container, token, tuneId); + if (obj == NULL) { + return -1; + } + + container->obj.area.width = SCREEN_WIDTH; + container->obj.area.height = 128; + container->layout = VERTICAL; + container->nbChildren = 4; // progress-bar + text + line + button + container->children + = (nbgl_obj_t **) nbgl_containerPoolGet(container->nbChildren, layoutInt->layer); + container->obj.alignment = BOTTOM_MIDDLE; + container->obj.touchMask = ((1 << TOUCHING) | (1 << TOUCH_RELEASED) | (1 << OUT_OF_TOUCH)); + + button = (nbgl_button_t *) nbgl_objPoolGet(BUTTON, layoutInt->layer); + button->obj.alignmentMarginX = BORDER_MARGIN; + button->obj.alignment = MID_RIGHT; + button->innerColor = BLACK; + button->foregroundColor = WHITE; + button->borderColor = BLACK; + button->obj.area.width = BUTTON_DIAMETER; + button->obj.area.height = BUTTON_DIAMETER; + button->radius = BUTTON_RADIUS; + button->icon = PIC(&C_check32px); + container->children[0] = (nbgl_obj_t *) button; + + textArea = (nbgl_text_area_t *) nbgl_objPoolGet(TEXT_AREA, layoutInt->layer); + textArea->textColor = BLACK; + textArea->text = PIC(text); + textArea->textAlignment = MID_LEFT; + textArea->fontId = BAGL_FONT_INTER_MEDIUM_32px; + textArea->wrapping = true; + textArea->obj.area.width + = container->obj.area.width - 3 * BORDER_MARGIN - button->obj.area.width; + textArea->obj.area.height = nbgl_getTextHeightInWidth( + textArea->fontId, textArea->text, textArea->obj.area.width, textArea->wrapping); + textArea->style = NO_STYLE; + textArea->obj.alignment = MID_LEFT; + textArea->obj.alignmentMarginX = BORDER_MARGIN; + container->children[1] = (nbgl_obj_t *) textArea; + + line = createHorizontalLine(layoutInt->layer); + line->offset = 3; + line->obj.alignment = TOP_MIDDLE; + container->children[2] = (nbgl_obj_t *) line; + + progressBar = (nbgl_progress_bar_t *) nbgl_objPoolGet(PROGRESS_BAR, layoutInt->layer); + progressBar->withBorder = false; + progressBar->obj.area.width = container->obj.area.width; + progressBar->obj.area.height = 8; + progressBar->obj.alignment = TOP_MIDDLE; + progressBar->obj.alignmentMarginY = 4; + progressBar->obj.alignTo = NULL; + container->children[3] = (nbgl_obj_t *) progressBar; + + // set this new container as child of the main container + addObjectToLayout(layoutInt, (nbgl_obj_t *) container); + + return 0; } /** - * @brief Creates a touchable text at the footer of the screen, separated with a thin line from the rest of the screen. + * @brief Creates a touchable text at the footer of the screen, separated with a thin line from the + * rest of the screen. * * @param layout the current layout * @param text text to used in the footer @@ -1747,45 +1903,52 @@ int nbgl_layoutAddLongPressButton(nbgl_layout_t *layout, const char *text, uint8 * @param tuneId if not @ref NBGL_NO_TUNE, a tune will be played when button is long pressed * @return >= 0 if OK */ -int nbgl_layoutAddFooter(nbgl_layout_t *layout, const char *text, uint8_t token, tune_index_e tuneId) { - nbgl_layoutInternal_t *layoutInt = (nbgl_layoutInternal_t *)layout; - layoutObj_t *obj; - nbgl_text_area_t *textArea; - nbgl_line_t *line; - - LOG_DEBUG(LAYOUT_LOGGER,"nbgl_layoutAddFooter():\n"); - if (layout == NULL) - return -1; - - textArea = (nbgl_text_area_t *)nbgl_objPoolGet(TEXT_AREA,layoutInt->layer); - obj = addCallbackObj(layoutInt,(nbgl_obj_t*)textArea,token,tuneId); - if (obj == NULL) - return -1; - - textArea->obj.alignment = BOTTOM_MIDDLE; - textArea->textColor = BLACK; - textArea->obj.area.width = AVAILABLE_WIDTH; - textArea->obj.area.height = BUTTON_DIAMETER; - textArea->text = PIC(text); - textArea->fontId = BAGL_FONT_INTER_SEMIBOLD_24px; - textArea->textAlignment = CENTER; - textArea->obj.touchMask = (1 << TOUCHED); - layoutInt->children[layoutInt->nbChildren] = (nbgl_obj_t*)textArea; - layoutInt->nbChildren++; - - line = createHorizontalLine(layoutInt->layer); - line->obj.alignTo = (nbgl_obj_t*)textArea; - line->obj.alignment = TOP_MIDDLE; - layoutInt->children[layoutInt->nbChildren] = (nbgl_obj_t*)line; - layoutInt->nbChildren++; - - layoutInt->container->obj.area.height -= textArea->obj.area.height+line->obj.area.height; - - return 0; +int nbgl_layoutAddFooter(nbgl_layout_t *layout, + const char *text, + uint8_t token, + tune_index_e tuneId) +{ + nbgl_layoutInternal_t *layoutInt = (nbgl_layoutInternal_t *) layout; + layoutObj_t *obj; + nbgl_text_area_t *textArea; + nbgl_line_t *line; + + LOG_DEBUG(LAYOUT_LOGGER, "nbgl_layoutAddFooter():\n"); + if (layout == NULL) { + return -1; + } + + textArea = (nbgl_text_area_t *) nbgl_objPoolGet(TEXT_AREA, layoutInt->layer); + obj = addCallbackObj(layoutInt, (nbgl_obj_t *) textArea, token, tuneId); + if (obj == NULL) { + return -1; + } + + textArea->obj.alignment = BOTTOM_MIDDLE; + textArea->textColor = BLACK; + textArea->obj.area.width = AVAILABLE_WIDTH; + textArea->obj.area.height = BUTTON_DIAMETER; + textArea->text = PIC(text); + textArea->fontId = BAGL_FONT_INTER_SEMIBOLD_24px; + textArea->textAlignment = CENTER; + textArea->obj.touchMask = (1 << TOUCHED); + layoutInt->children[layoutInt->nbChildren] = (nbgl_obj_t *) textArea; + layoutInt->nbChildren++; + + line = createHorizontalLine(layoutInt->layer); + line->obj.alignTo = (nbgl_obj_t *) textArea; + line->obj.alignment = TOP_MIDDLE; + layoutInt->children[layoutInt->nbChildren] = (nbgl_obj_t *) line; + layoutInt->nbChildren++; + + layoutInt->container->obj.area.height -= textArea->obj.area.height + line->obj.area.height; + + return 0; } /** - * @brief Creates 2 touchable texts at the footer of the screen, separated with a thin line from the rest of the screen, and from each other. + * @brief Creates 2 touchable texts at the footer of the screen, separated with a thin line from the + * rest of the screen, and from each other. * * @param layout the current layout * @param leftText text to used in the left part of footer @@ -1795,76 +1958,85 @@ int nbgl_layoutAddFooter(nbgl_layout_t *layout, const char *text, uint8_t token, * @param tuneId if not @ref NBGL_NO_TUNE, a tune will be played when button is long pressed * @return >= 0 if OK */ -int nbgl_layoutAddSplitFooter(nbgl_layout_t *layout, const char *leftText, uint8_t leftToken, const char *rightText, uint8_t rightToken, tune_index_e tuneId) { - nbgl_layoutInternal_t *layoutInt = (nbgl_layoutInternal_t *)layout; - layoutObj_t *obj; - nbgl_text_area_t *textArea; - nbgl_line_t *line; - - LOG_DEBUG(LAYOUT_LOGGER,"nbgl_layoutAddSplitFooter():\n"); - if (layout == NULL) - return -1; - - // create left touchable text - textArea = (nbgl_text_area_t *)nbgl_objPoolGet(TEXT_AREA,layoutInt->layer); - obj = addCallbackObj(layoutInt,(nbgl_obj_t*)textArea,leftToken,tuneId); - if (obj == NULL) - return -1; - - textArea->obj.alignment = BOTTOM_LEFT; - textArea->textColor = BLACK; - textArea->obj.area.width = AVAILABLE_WIDTH/2; - textArea->obj.area.height = BUTTON_DIAMETER; - textArea->text = PIC(leftText); - textArea->fontId = BAGL_FONT_INTER_SEMIBOLD_24px; - textArea->textAlignment = CENTER; - textArea->obj.touchMask = (1 << TOUCHED); - layoutInt->children[layoutInt->nbChildren] = (nbgl_obj_t*)textArea; - layoutInt->nbChildren++; - - // create right touchable text - textArea = (nbgl_text_area_t *)nbgl_objPoolGet(TEXT_AREA,layoutInt->layer); - obj = addCallbackObj(layoutInt,(nbgl_obj_t*)textArea,rightToken,tuneId); - if (obj == NULL) - return -1; - - textArea->obj.alignment = BOTTOM_RIGHT; - textArea->textColor = BLACK; - textArea->obj.area.width = AVAILABLE_WIDTH/2; - textArea->obj.area.height = BUTTON_DIAMETER; - textArea->text = PIC(rightText); - textArea->fontId = BAGL_FONT_INTER_SEMIBOLD_24px; - textArea->textAlignment = CENTER; - textArea->obj.touchMask = (1 << TOUCHED); - layoutInt->children[layoutInt->nbChildren] = (nbgl_obj_t*)textArea; - layoutInt->nbChildren++; - - // create horizontal line separating footer from main container - line = createHorizontalLine(layoutInt->layer); - line->obj.alignTo = layoutInt->children[layoutInt->nbChildren-2]; - line->obj.alignment = TOP_LEFT; - layoutInt->children[layoutInt->nbChildren] = (nbgl_obj_t*)line; - layoutInt->nbChildren++; - - // create vertical line separating both text areas - line = (nbgl_line_t*)nbgl_objPoolGet(LINE,layoutInt->layer); - line->lineColor = LIGHT_GRAY; - line->obj.area.width = 1; - line->obj.area.height = textArea->obj.area.height+4; - line->direction = VERTICAL; - line->thickness = 1; - line->obj.alignment = BOTTOM_MIDDLE; - layoutInt->children[layoutInt->nbChildren] = (nbgl_obj_t*)line; - layoutInt->nbChildren++; - - layoutInt->container->obj.area.height -= textArea->obj.area.height+4; - - return 0; +int nbgl_layoutAddSplitFooter(nbgl_layout_t *layout, + const char *leftText, + uint8_t leftToken, + const char *rightText, + uint8_t rightToken, + tune_index_e tuneId) +{ + nbgl_layoutInternal_t *layoutInt = (nbgl_layoutInternal_t *) layout; + layoutObj_t *obj; + nbgl_text_area_t *textArea; + nbgl_line_t *line; + + LOG_DEBUG(LAYOUT_LOGGER, "nbgl_layoutAddSplitFooter():\n"); + if (layout == NULL) { + return -1; + } + + // create left touchable text + textArea = (nbgl_text_area_t *) nbgl_objPoolGet(TEXT_AREA, layoutInt->layer); + obj = addCallbackObj(layoutInt, (nbgl_obj_t *) textArea, leftToken, tuneId); + if (obj == NULL) { + return -1; + } + + textArea->obj.alignment = BOTTOM_LEFT; + textArea->textColor = BLACK; + textArea->obj.area.width = AVAILABLE_WIDTH / 2; + textArea->obj.area.height = BUTTON_DIAMETER; + textArea->text = PIC(leftText); + textArea->fontId = BAGL_FONT_INTER_SEMIBOLD_24px; + textArea->textAlignment = CENTER; + textArea->obj.touchMask = (1 << TOUCHED); + layoutInt->children[layoutInt->nbChildren] = (nbgl_obj_t *) textArea; + layoutInt->nbChildren++; + + // create right touchable text + textArea = (nbgl_text_area_t *) nbgl_objPoolGet(TEXT_AREA, layoutInt->layer); + obj = addCallbackObj(layoutInt, (nbgl_obj_t *) textArea, rightToken, tuneId); + if (obj == NULL) { + return -1; + } + + textArea->obj.alignment = BOTTOM_RIGHT; + textArea->textColor = BLACK; + textArea->obj.area.width = AVAILABLE_WIDTH / 2; + textArea->obj.area.height = BUTTON_DIAMETER; + textArea->text = PIC(rightText); + textArea->fontId = BAGL_FONT_INTER_SEMIBOLD_24px; + textArea->textAlignment = CENTER; + textArea->obj.touchMask = (1 << TOUCHED); + layoutInt->children[layoutInt->nbChildren] = (nbgl_obj_t *) textArea; + layoutInt->nbChildren++; + + // create horizontal line separating footer from main container + line = createHorizontalLine(layoutInt->layer); + line->obj.alignTo = layoutInt->children[layoutInt->nbChildren - 2]; + line->obj.alignment = TOP_LEFT; + layoutInt->children[layoutInt->nbChildren] = (nbgl_obj_t *) line; + layoutInt->nbChildren++; + + // create vertical line separating both text areas + line = (nbgl_line_t *) nbgl_objPoolGet(LINE, layoutInt->layer); + line->lineColor = LIGHT_GRAY; + line->obj.area.width = 1; + line->obj.area.height = textArea->obj.area.height + 4; + line->direction = VERTICAL; + line->thickness = 1; + line->obj.alignment = BOTTOM_MIDDLE; + layoutInt->children[layoutInt->nbChildren] = (nbgl_obj_t *) line; + layoutInt->nbChildren++; + + layoutInt->container->obj.area.height -= textArea->obj.area.height + 4; + + return 0; } /** - * @brief Creates a kind of navigation bar with an optional <- arrow on the left. This widget is placed on top of the - * main container + * @brief Creates a kind of navigation bar with an optional <- arrow on the left. This widget is + * placed on top of the main container * * @param layout the current layout * @param activePage current page [O,(nbPages-1)] @@ -1874,59 +2046,68 @@ int nbgl_layoutAddSplitFooter(nbgl_layout_t *layout, const char *leftText, uint8 * @param tuneId if not @ref NBGL_NO_TUNE, a tune will be played when back button is pressed * @return >= 0 if OK */ -int nbgl_layoutAddProgressIndicator(nbgl_layout_t *layout, uint8_t activePage, uint8_t nbPages, bool withBack, uint8_t backToken, tune_index_e tuneId) { - layoutObj_t *obj; - nbgl_container_t *container; - nbgl_button_t *button; - nbgl_layoutInternal_t *layoutInt = (nbgl_layoutInternal_t *)layout; - - LOG_DEBUG(LAYOUT_LOGGER,"nbgl_layoutAddProgressIndicator():\n"); - if (layout == NULL) - return -1; - - container = (nbgl_container_t *)nbgl_objPoolGet(CONTAINER, layoutInt->layer); - container->obj.area.width = SCREEN_WIDTH; - container->obj.area.height = BUTTON_DIAMETER+8; - container->layout = VERTICAL; - container->nbChildren = 2; - container->children = (nbgl_obj_t**)nbgl_containerPoolGet(container->nbChildren,layoutInt->layer); - container->obj.alignment = TOP_MIDDLE; - container->obj.alignTo = NULL; - - if (nbPages > 1) { - nbgl_page_indicator_t *navigationBar; - - navigationBar = (nbgl_page_indicator_t *)nbgl_objPoolGet(PAGE_INDICATOR,layoutInt->layer); - navigationBar->activePage = activePage; - navigationBar->nbPages = nbPages; - navigationBar->obj.area.width = SCREEN_WIDTH-2*100; - navigationBar->obj.alignment = CENTER; - container->children[0] = (nbgl_obj_t*)navigationBar; - } - - if ((withBack== true) && ((nbPages < 2)||(activePage > 0))) { - button = (nbgl_button_t *)nbgl_objPoolGet(BUTTON,layoutInt->layer); - obj = addCallbackObj(layoutInt,(nbgl_obj_t*)button,backToken,tuneId); - if (obj == NULL) - return -1; - - button->obj.alignment = MID_LEFT; - button->innerColor = WHITE; - button->foregroundColor = BLACK; - button->borderColor = WHITE; - button->obj.area.width = BUTTON_DIAMETER; - button->obj.area.height = BUTTON_DIAMETER; - button->radius = BUTTON_RADIUS; - button->text = NULL; - button->icon = PIC(&C_leftArrow32px); - button->obj.touchMask = (1<children[1] = (nbgl_obj_t*)button; - } +int nbgl_layoutAddProgressIndicator(nbgl_layout_t *layout, + uint8_t activePage, + uint8_t nbPages, + bool withBack, + uint8_t backToken, + tune_index_e tuneId) +{ + layoutObj_t *obj; + nbgl_container_t *container; + nbgl_button_t *button; + nbgl_layoutInternal_t *layoutInt = (nbgl_layoutInternal_t *) layout; + + LOG_DEBUG(LAYOUT_LOGGER, "nbgl_layoutAddProgressIndicator():\n"); + if (layout == NULL) { + return -1; + } - // set this new container as child of the main container - addObjectToLayout(layoutInt,(nbgl_obj_t*)container); + container = (nbgl_container_t *) nbgl_objPoolGet(CONTAINER, layoutInt->layer); + container->obj.area.width = SCREEN_WIDTH; + container->obj.area.height = BUTTON_DIAMETER + 8; + container->layout = VERTICAL; + container->nbChildren = 2; + container->children + = (nbgl_obj_t **) nbgl_containerPoolGet(container->nbChildren, layoutInt->layer); + container->obj.alignment = TOP_MIDDLE; + container->obj.alignTo = NULL; + + if (nbPages > 1) { + nbgl_page_indicator_t *navigationBar; + + navigationBar = (nbgl_page_indicator_t *) nbgl_objPoolGet(PAGE_INDICATOR, layoutInt->layer); + navigationBar->activePage = activePage; + navigationBar->nbPages = nbPages; + navigationBar->obj.area.width = SCREEN_WIDTH - 2 * 100; + navigationBar->obj.alignment = CENTER; + container->children[0] = (nbgl_obj_t *) navigationBar; + } - return 0; + if ((withBack == true) && ((nbPages < 2) || (activePage > 0))) { + button = (nbgl_button_t *) nbgl_objPoolGet(BUTTON, layoutInt->layer); + obj = addCallbackObj(layoutInt, (nbgl_obj_t *) button, backToken, tuneId); + if (obj == NULL) { + return -1; + } + + button->obj.alignment = MID_LEFT; + button->innerColor = WHITE; + button->foregroundColor = BLACK; + button->borderColor = WHITE; + button->obj.area.width = BUTTON_DIAMETER; + button->obj.area.height = BUTTON_DIAMETER; + button->radius = BUTTON_RADIUS; + button->text = NULL; + button->icon = PIC(&C_leftArrow32px); + button->obj.touchMask = (1 << TOUCHED); + container->children[1] = (nbgl_obj_t *) button; + } + + // set this new container as child of the main container + addObjectToLayout(layoutInt, (nbgl_obj_t *) container); + + return 0; } /** @@ -1937,52 +2118,55 @@ int nbgl_layoutAddProgressIndicator(nbgl_layout_t *layout, uint8_t activePage, u * @param fixed if set to true, the spinner won't spin and be entirely black * @return >= 0 if OK */ -int nbgl_layoutAddSpinner(nbgl_layout_t *layout, const char *text, bool fixed) { - nbgl_layoutInternal_t *layoutInt = (nbgl_layoutInternal_t *)layout; - nbgl_text_area_t *textArea; - nbgl_spinner_t *spinner; - - LOG_DEBUG(LAYOUT_LOGGER,"nbgl_layoutAddSpinner():\n"); - if (layout == NULL) - return -1; - - // create spinner - spinner = (nbgl_spinner_t*)nbgl_objPoolGet(SPINNER, layoutInt->layer); - spinner->position = fixed? 0xFF : 0; - spinner->obj.alignmentMarginY = -20; - spinner->obj.alignTo = NULL; - spinner->obj.alignment = CENTER; - // set this new spinner as child of the container - addObjectToLayout(layoutInt,(nbgl_obj_t*)spinner); - - // create text area - textArea = (nbgl_text_area_t*)nbgl_objPoolGet(TEXT_AREA, layoutInt->layer); - textArea->textColor = BLACK; - textArea->text = PIC(text); - textArea->textAlignment = CENTER; - textArea->fontId = BAGL_FONT_INTER_REGULAR_24px; - textArea->wrapping = true; - textArea->obj.alignmentMarginY = 20; - textArea->obj.alignTo = (nbgl_obj_t*)spinner; - textArea->obj.alignment = BOTTOM_MIDDLE; - textArea->obj.area.width = AVAILABLE_WIDTH; - textArea->obj.area.height = nbgl_getTextHeightInWidth(textArea->fontId, textArea->text, textArea->obj.area.width, textArea->wrapping); - textArea->style = NO_STYLE; - - // set this new spinner as child of the container - addObjectToLayout(layoutInt,(nbgl_obj_t*)textArea); - - if (!fixed) { - // update ticker to update the spinner periodically - nbgl_screenTickerConfiguration_t tickerCfg; - - tickerCfg.tickerIntervale = SPINNER_REFRESH_PERIOD; //ms - tickerCfg.tickerValue = SPINNER_REFRESH_PERIOD; //ms - tickerCfg.tickerCallback = &spinnerTickerCallback; - nbgl_screenUpdateTicker(layoutInt->layer,&tickerCfg); - } - - return 0; +int nbgl_layoutAddSpinner(nbgl_layout_t *layout, const char *text, bool fixed) +{ + nbgl_layoutInternal_t *layoutInt = (nbgl_layoutInternal_t *) layout; + nbgl_text_area_t *textArea; + nbgl_spinner_t *spinner; + + LOG_DEBUG(LAYOUT_LOGGER, "nbgl_layoutAddSpinner():\n"); + if (layout == NULL) { + return -1; + } + + // create spinner + spinner = (nbgl_spinner_t *) nbgl_objPoolGet(SPINNER, layoutInt->layer); + spinner->position = fixed ? 0xFF : 0; + spinner->obj.alignmentMarginY = -20; + spinner->obj.alignTo = NULL; + spinner->obj.alignment = CENTER; + // set this new spinner as child of the container + addObjectToLayout(layoutInt, (nbgl_obj_t *) spinner); + + // create text area + textArea = (nbgl_text_area_t *) nbgl_objPoolGet(TEXT_AREA, layoutInt->layer); + textArea->textColor = BLACK; + textArea->text = PIC(text); + textArea->textAlignment = CENTER; + textArea->fontId = BAGL_FONT_INTER_REGULAR_24px; + textArea->wrapping = true; + textArea->obj.alignmentMarginY = 20; + textArea->obj.alignTo = (nbgl_obj_t *) spinner; + textArea->obj.alignment = BOTTOM_MIDDLE; + textArea->obj.area.width = AVAILABLE_WIDTH; + textArea->obj.area.height = nbgl_getTextHeightInWidth( + textArea->fontId, textArea->text, textArea->obj.area.width, textArea->wrapping); + textArea->style = NO_STYLE; + + // set this new spinner as child of the container + addObjectToLayout(layoutInt, (nbgl_obj_t *) textArea); + + if (!fixed) { + // update ticker to update the spinner periodically + nbgl_screenTickerConfiguration_t tickerCfg; + + tickerCfg.tickerIntervale = SPINNER_REFRESH_PERIOD; // ms + tickerCfg.tickerValue = SPINNER_REFRESH_PERIOD; // ms + tickerCfg.tickerCallback = &spinnerTickerCallback; + nbgl_screenUpdateTicker(layoutInt->layer, &tickerCfg); + } + + return 0; } #ifdef NBGL_KEYBOARD @@ -1993,29 +2177,31 @@ int nbgl_layoutAddSpinner(nbgl_layout_t *layout, const char *text, bool fixed) { * @param kbdInfo configuration of the keyboard to draw (including the callback when touched) * @return the index of keyboard, to use in @ref nbgl_layoutUpdateKeyboard() */ -int nbgl_layoutAddKeyboard(nbgl_layout_t *layout, const nbgl_layoutKbd_t *kbdInfo) { - nbgl_layoutInternal_t *layoutInt = (nbgl_layoutInternal_t *)layout; - nbgl_keyboard_t *keyboard; - - LOG_DEBUG(LAYOUT_LOGGER,"nbgl_layoutAddKeyboard():\n"); - if (layout == NULL) - return -1; - - // create keyboard - keyboard = (nbgl_keyboard_t*)nbgl_objPoolGet(KEYBOARD, layoutInt->layer); - keyboard->obj.alignmentMarginY = 64; - keyboard->obj.alignment = BOTTOM_MIDDLE; - keyboard->borderColor = LIGHT_GRAY; - keyboard->callback = PIC(kbdInfo->callback); - keyboard->lettersOnly = kbdInfo->lettersOnly; - keyboard->mode = kbdInfo->mode; - keyboard->keyMask = kbdInfo->keyMask; - keyboard->casing = kbdInfo->casing; - // set this new keyboard as child of the container - addObjectToLayout(layoutInt,(nbgl_obj_t*)keyboard); - - // return index of keyboard to be modified later on - return (layoutInt->container->nbChildren-1); +int nbgl_layoutAddKeyboard(nbgl_layout_t *layout, const nbgl_layoutKbd_t *kbdInfo) +{ + nbgl_layoutInternal_t *layoutInt = (nbgl_layoutInternal_t *) layout; + nbgl_keyboard_t *keyboard; + + LOG_DEBUG(LAYOUT_LOGGER, "nbgl_layoutAddKeyboard():\n"); + if (layout == NULL) { + return -1; + } + + // create keyboard + keyboard = (nbgl_keyboard_t *) nbgl_objPoolGet(KEYBOARD, layoutInt->layer); + keyboard->obj.alignmentMarginY = 64; + keyboard->obj.alignment = BOTTOM_MIDDLE; + keyboard->borderColor = LIGHT_GRAY; + keyboard->callback = PIC(kbdInfo->callback); + keyboard->lettersOnly = kbdInfo->lettersOnly; + keyboard->mode = kbdInfo->mode; + keyboard->keyMask = kbdInfo->keyMask; + keyboard->casing = kbdInfo->casing; + // set this new keyboard as child of the container + addObjectToLayout(layoutInt, (nbgl_obj_t *) keyboard); + + // return index of keyboard to be modified later on + return (layoutInt->container->nbChildren - 1); } /** @@ -2028,27 +2214,33 @@ int nbgl_layoutAddKeyboard(nbgl_layout_t *layout, const nbgl_layoutKbd_t *kbdInf * @param casing casing to use * @return >=0 if OK */ -int nbgl_layoutUpdateKeyboard(nbgl_layout_t *layout, uint8_t index, uint32_t keyMask, bool updateCasing, keyboardCase_t casing) { - nbgl_layoutInternal_t *layoutInt = (nbgl_layoutInternal_t *)layout; - nbgl_keyboard_t *keyboard; - - LOG_DEBUG(LAYOUT_LOGGER,"nbgl_layoutUpdateKeyboard(): keyMask = 0x%X\n",keyMask); - if (layout == NULL) - return -1; - - // get keyboard at given index - keyboard = (nbgl_keyboard_t*)layoutInt->container->children[index]; - if ((keyboard == NULL) || (keyboard->obj.type != KEYBOARD)) { - return -1; - } - keyboard->keyMask = keyMask; - if (updateCasing) { - keyboard->casing = casing; - } - - nbgl_redrawObject((nbgl_obj_t*)keyboard,NULL,false); - - return 0; +int nbgl_layoutUpdateKeyboard(nbgl_layout_t *layout, + uint8_t index, + uint32_t keyMask, + bool updateCasing, + keyboardCase_t casing) +{ + nbgl_layoutInternal_t *layoutInt = (nbgl_layoutInternal_t *) layout; + nbgl_keyboard_t *keyboard; + + LOG_DEBUG(LAYOUT_LOGGER, "nbgl_layoutUpdateKeyboard(): keyMask = 0x%X\n", keyMask); + if (layout == NULL) { + return -1; + } + + // get keyboard at given index + keyboard = (nbgl_keyboard_t *) layoutInt->container->children[index]; + if ((keyboard == NULL) || (keyboard->obj.type != KEYBOARD)) { + return -1; + } + keyboard->keyMask = keyMask; + if (updateCasing) { + keyboard->casing = casing; + } + + nbgl_redrawObject((nbgl_obj_t *) keyboard, NULL, false); + + return 0; } /** @@ -2058,25 +2250,27 @@ int nbgl_layoutUpdateKeyboard(nbgl_layout_t *layout, uint8_t index, uint32_t key * @param index index returned by @ref nbgl_layoutAddKeyboard() * @return true if keyboard needs a refresh */ -bool nbgl_layoutKeyboardNeedsRefresh(nbgl_layout_t *layout, uint8_t index) { - nbgl_layoutInternal_t *layoutInt = (nbgl_layoutInternal_t *)layout; - nbgl_keyboard_t *keyboard; - - LOG_DEBUG(LAYOUT_LOGGER,"nbgl_layoutKeyboardNeedsRefresh(): \n"); - if (layout == NULL) - return -1; - - // get keyboard at given index - keyboard = (nbgl_keyboard_t*)layoutInt->container->children[index]; - if ((keyboard == NULL) || (keyboard->obj.type != KEYBOARD)) { - return -1; - } - if (keyboard->needsRefresh) { - keyboard->needsRefresh = false; - return true; - } - - return false; +bool nbgl_layoutKeyboardNeedsRefresh(nbgl_layout_t *layout, uint8_t index) +{ + nbgl_layoutInternal_t *layoutInt = (nbgl_layoutInternal_t *) layout; + nbgl_keyboard_t *keyboard; + + LOG_DEBUG(LAYOUT_LOGGER, "nbgl_layoutKeyboardNeedsRefresh(): \n"); + if (layout == NULL) { + return -1; + } + + // get keyboard at given index + keyboard = (nbgl_keyboard_t *) layoutInt->container->children[index]; + if ((keyboard == NULL) || (keyboard->obj.type != KEYBOARD)) { + return -1; + } + if (keyboard->needsRefresh) { + keyboard->needsRefresh = false; + return true; + } + + return false; } /** @@ -2085,74 +2279,86 @@ bool nbgl_layoutKeyboardNeedsRefresh(nbgl_layout_t *layout, uint8_t index) { * @param layout the current layout * @param nbUsedButtons the number of actually used buttons * @param buttonTexts array of 4 strings for buttons (last ones can be NULL) - * @param firstButtonToken first token used for buttons, provided in onActionCallback (the next 3 values will be used for other buttons) + * @param firstButtonToken first token used for buttons, provided in onActionCallback (the next 3 + * values will be used for other buttons) * @param tuneId tune to play when any button is pressed * @return >= 0 if OK */ -int nbgl_layoutAddSuggestionButtons(nbgl_layout_t *layout, uint8_t nbUsedButtons, - const char *buttonTexts[NB_MAX_SUGGESTION_BUTTONS], - int firstButtonToken, tune_index_e tuneId) { - layoutObj_t *obj; - nbgl_container_t *container; - nbgl_layoutInternal_t *layoutInt = (nbgl_layoutInternal_t *)layout; - - LOG_DEBUG(LAYOUT_LOGGER,"nbgl_layoutAddSuggestionButtons():\n"); - if (layout == NULL) - return -1; - - container = (nbgl_container_t *)nbgl_objPoolGet(CONTAINER, layoutInt->layer); - container->obj.area.width = SCREEN_WIDTH; - container->obj.area.height = 2*64+8; - container->layout = VERTICAL; - container->nbChildren = NB_MAX_SUGGESTION_BUTTONS; - container->children = (nbgl_obj_t**)nbgl_containerPoolGet(container->nbChildren,layoutInt->layer); - container->obj.alignmentMarginY = BORDER_MARGIN; - container->obj.alignment = TOP_MIDDLE; - container->obj.alignTo = layoutInt->container->children[layoutInt->container->nbChildren-1]; - - // create suggestion buttons, even if not displayed at first - nbgl_objPoolGetArray(BUTTON,NB_MAX_SUGGESTION_BUTTONS,0,(nbgl_obj_t**)&choiceButtons); - for (int i=0;iinnerColor = BLACK; - choiceButtons[i]->borderColor = BLACK; - choiceButtons[i]->foregroundColor = WHITE; - choiceButtons[i]->obj.area.width = (SCREEN_WIDTH-2*BORDER_MARGIN-8)/2; - choiceButtons[i]->obj.area.height = 64; - choiceButtons[i]->radius = RADIUS_32_PIXELS; - choiceButtons[i]->fontId = BAGL_FONT_INTER_SEMIBOLD_24px_1bpp; - choiceButtons[i]->icon = NULL; - if ((i%2) == 0) { - choiceButtons[i]->obj.alignmentMarginX = BORDER_MARGIN; - if (i != 0) - choiceButtons[i]->obj.alignmentMarginY = 8; - choiceButtons[i]->obj.alignment = NO_ALIGNMENT; +int nbgl_layoutAddSuggestionButtons(nbgl_layout_t *layout, + uint8_t nbUsedButtons, + const char *buttonTexts[NB_MAX_SUGGESTION_BUTTONS], + int firstButtonToken, + tune_index_e tuneId) +{ + layoutObj_t *obj; + nbgl_container_t *container; + nbgl_layoutInternal_t *layoutInt = (nbgl_layoutInternal_t *) layout; + + LOG_DEBUG(LAYOUT_LOGGER, "nbgl_layoutAddSuggestionButtons():\n"); + if (layout == NULL) { + return -1; } - else { - choiceButtons[i]->obj.alignmentMarginX = 8; - choiceButtons[i]->obj.alignment = MID_RIGHT; - choiceButtons[i]->obj.alignTo = (nbgl_obj_t*)choiceButtons[i-1]; - } - choiceButtons[i]->text = buttonTexts[i]; - choiceButtons[i]->obj.touchMask = (1<children[i] = (nbgl_obj_t*)choiceButtons[i]; - else - container->children[i] = NULL; - } - // set this new container as child of the main container - addObjectToLayout(layoutInt,(nbgl_obj_t*)container); - - // return index of container to be modified later on - return (layoutInt->container->nbChildren-1); + + container = (nbgl_container_t *) nbgl_objPoolGet(CONTAINER, layoutInt->layer); + container->obj.area.width = SCREEN_WIDTH; + container->obj.area.height = 2 * 64 + 8; + container->layout = VERTICAL; + container->nbChildren = NB_MAX_SUGGESTION_BUTTONS; + container->children + = (nbgl_obj_t **) nbgl_containerPoolGet(container->nbChildren, layoutInt->layer); + container->obj.alignmentMarginY = BORDER_MARGIN; + container->obj.alignment = TOP_MIDDLE; + container->obj.alignTo = layoutInt->container->children[layoutInt->container->nbChildren - 1]; + + // create suggestion buttons, even if not displayed at first + nbgl_objPoolGetArray(BUTTON, NB_MAX_SUGGESTION_BUTTONS, 0, (nbgl_obj_t **) &choiceButtons); + for (int i = 0; i < NB_MAX_SUGGESTION_BUTTONS; i++) { + obj = addCallbackObj( + layoutInt, (nbgl_obj_t *) choiceButtons[i], firstButtonToken + i, tuneId); + if (obj == NULL) { + return -1; + } + + choiceButtons[i]->innerColor = BLACK; + choiceButtons[i]->borderColor = BLACK; + choiceButtons[i]->foregroundColor = WHITE; + choiceButtons[i]->obj.area.width = (SCREEN_WIDTH - 2 * BORDER_MARGIN - 8) / 2; + choiceButtons[i]->obj.area.height = 64; + choiceButtons[i]->radius = RADIUS_32_PIXELS; + choiceButtons[i]->fontId = BAGL_FONT_INTER_SEMIBOLD_24px_1bpp; + choiceButtons[i]->icon = NULL; + if ((i % 2) == 0) { + choiceButtons[i]->obj.alignmentMarginX = BORDER_MARGIN; + if (i != 0) { + choiceButtons[i]->obj.alignmentMarginY = 8; + } + choiceButtons[i]->obj.alignment = NO_ALIGNMENT; + } + else { + choiceButtons[i]->obj.alignmentMarginX = 8; + choiceButtons[i]->obj.alignment = MID_RIGHT; + choiceButtons[i]->obj.alignTo = (nbgl_obj_t *) choiceButtons[i - 1]; + } + choiceButtons[i]->text = buttonTexts[i]; + choiceButtons[i]->obj.touchMask = (1 << TOUCHED); + // some buttons may not be visible + if (i < nbUsedButtons) { + container->children[i] = (nbgl_obj_t *) choiceButtons[i]; + } + else { + container->children[i] = NULL; + } + } + // set this new container as child of the main container + addObjectToLayout(layoutInt, (nbgl_obj_t *) container); + + // return index of container to be modified later on + return (layoutInt->container->nbChildren - 1); } /** - * @brief Updates the number and/or the text suggestion buttons created with @ref nbgl_layoutAddSuggestionButtons() + * @brief Updates the number and/or the text suggestion buttons created with @ref + * nbgl_layoutAddSuggestionButtons() * * @param layout the current layout * @param index index returned by @ref nbgl_layoutAddSuggestionButtons() @@ -2160,41 +2366,46 @@ int nbgl_layoutAddSuggestionButtons(nbgl_layout_t *layout, uint8_t nbUsedButtons * @param buttonTexts array of 4 strings for buttons (last ones can be NULL) * @return >= 0 if OK */ -int nbgl_layoutUpdateSuggestionButtons(nbgl_layout_t *layout, uint8_t index, uint8_t nbUsedButtons, - const char *buttonTexts[NB_MAX_SUGGESTION_BUTTONS]) { - nbgl_layoutInternal_t *layoutInt = (nbgl_layoutInternal_t *)layout; - nbgl_container_t *container; - - LOG_DEBUG(LAYOUT_LOGGER,"nbgl_layoutUpdateSuggestionButtons():\n"); - if (layout == NULL) - return -1; - - container = (nbgl_container_t *)layoutInt->container->children[index]; - if ((container == NULL) || (container->obj.type != CONTAINER)) { - return -1; - } - - // update suggestion buttons - for (int i=0;itext = buttonTexts[i]; - // some buttons may not be visible - if (ichildren[i] = (nbgl_obj_t*)choiceButtons[i]; - else - container->children[i] = NULL; - } - container->forceClean = true; - - nbgl_redrawObject((nbgl_obj_t*)container,NULL,false); - - return 0; +int nbgl_layoutUpdateSuggestionButtons(nbgl_layout_t *layout, + uint8_t index, + uint8_t nbUsedButtons, + const char *buttonTexts[NB_MAX_SUGGESTION_BUTTONS]) +{ + nbgl_layoutInternal_t *layoutInt = (nbgl_layoutInternal_t *) layout; + nbgl_container_t *container; + + LOG_DEBUG(LAYOUT_LOGGER, "nbgl_layoutUpdateSuggestionButtons():\n"); + if (layout == NULL) { + return -1; + } + + container = (nbgl_container_t *) layoutInt->container->children[index]; + if ((container == NULL) || (container->obj.type != CONTAINER)) { + return -1; + } + + // update suggestion buttons + for (int i = 0; i < NB_MAX_SUGGESTION_BUTTONS; i++) { + choiceButtons[i]->text = buttonTexts[i]; + // some buttons may not be visible + if (i < nbUsedButtons) { + container->children[i] = (nbgl_obj_t *) choiceButtons[i]; + } + else { + container->children[i] = NULL; + } + } + container->forceClean = true; + + nbgl_redrawObject((nbgl_obj_t *) container, NULL, false); + + return 0; } /** - * @brief Adds a "text entry" area under the previously entered object. This area can be preceded (beginning of line) by - * an index, indicating for example the entered world. - * A vertical gray line is placed under the text. - * This text must be vertical placed in the screen with offsetY + * @brief Adds a "text entry" area under the previously entered object. This area can be preceded + * (beginning of line) by an index, indicating for example the entered world. A vertical gray line + * is placed under the text. This text must be vertical placed in the screen with offsetY * * @note This area is touchable * @@ -2207,77 +2418,85 @@ int nbgl_layoutUpdateSuggestionButtons(nbgl_layout_t *layout, uint8_t index, uin * @param token token provided in onActionCallback when this area is touched * @return >= 0 if OK */ -int nbgl_layoutAddEnteredText(nbgl_layout_t *layout, bool numbered, uint8_t number, const char *text, bool grayedOut, int offsetY, int token) { - nbgl_layoutInternal_t *layoutInt = (nbgl_layoutInternal_t *)layout; - nbgl_text_area_t *textArea; - nbgl_line_t *line; - layoutObj_t *obj; - - LOG_DEBUG(LAYOUT_LOGGER,"nbgl_layoutAddEnteredText():\n"); - if (layout == NULL) - return -1; - - // create gray line - line = (nbgl_line_t*)nbgl_objPoolGet(LINE, layoutInt->layer); - line->lineColor = LIGHT_GRAY; - line->obj.alignmentMarginY = offsetY; - line->obj.alignTo = layoutInt->container->children[layoutInt->container->nbChildren-1]; - line->obj.alignment = TOP_MIDDLE; - line->obj.area.width = SCREEN_WIDTH-2*32; - line->obj.area.height = 4; - line->direction = HORIZONTAL; - line->thickness = 2; - line->offset = 2; - // set this new line as child of the main container - addObjectToLayout(layoutInt,(nbgl_obj_t*)line); - - if (numbered) { - // create Word num typed text - textArea = (nbgl_text_area_t*)nbgl_objPoolGet(TEXT_AREA, layoutInt->layer); - textArea->textColor = BLACK; - snprintf(numText,sizeof(numText),"%d.",number); - textArea->text = numText; +int nbgl_layoutAddEnteredText(nbgl_layout_t *layout, + bool numbered, + uint8_t number, + const char *text, + bool grayedOut, + int offsetY, + int token) +{ + nbgl_layoutInternal_t *layoutInt = (nbgl_layoutInternal_t *) layout; + nbgl_text_area_t *textArea; + nbgl_line_t *line; + layoutObj_t *obj; + + LOG_DEBUG(LAYOUT_LOGGER, "nbgl_layoutAddEnteredText():\n"); + if (layout == NULL) { + return -1; + } + + // create gray line + line = (nbgl_line_t *) nbgl_objPoolGet(LINE, layoutInt->layer); + line->lineColor = LIGHT_GRAY; + line->obj.alignmentMarginY = offsetY; + line->obj.alignTo = layoutInt->container->children[layoutInt->container->nbChildren - 1]; + line->obj.alignment = TOP_MIDDLE; + line->obj.area.width = SCREEN_WIDTH - 2 * 32; + line->obj.area.height = 4; + line->direction = HORIZONTAL; + line->thickness = 2; + line->offset = 2; + // set this new line as child of the main container + addObjectToLayout(layoutInt, (nbgl_obj_t *) line); + + if (numbered) { + // create Word num typed text + textArea = (nbgl_text_area_t *) nbgl_objPoolGet(TEXT_AREA, layoutInt->layer); + textArea->textColor = BLACK; + snprintf(numText, sizeof(numText), "%d.", number); + textArea->text = numText; + textArea->textAlignment = MID_LEFT; + textArea->fontId = BAGL_FONT_INTER_MEDIUM_32px_1bpp; + textArea->obj.alignmentMarginY = 12; + textArea->obj.alignTo = (nbgl_obj_t *) line; + textArea->obj.alignment = TOP_LEFT; + textArea->obj.area.width = 50; + textArea->obj.area.height = nbgl_getFontLineHeight(textArea->fontId); + // set this new text area as child of the main container + addObjectToLayout(layoutInt, (nbgl_obj_t *) textArea); + } + + // create text area + textArea = (nbgl_text_area_t *) nbgl_objPoolGet(TEXT_AREA, layoutInt->layer); + textArea->textColor = grayedOut ? LIGHT_GRAY : BLACK; + textArea->text = text; textArea->textAlignment = MID_LEFT; - textArea->fontId = BAGL_FONT_INTER_MEDIUM_32px_1bpp; + textArea->fontId = BAGL_FONT_INTER_MEDIUM_32px_1bpp; textArea->obj.alignmentMarginY = 12; - textArea->obj.alignTo = (nbgl_obj_t*)line; - textArea->obj.alignment = TOP_LEFT; - textArea->obj.area.width = 50; - textArea->obj.area.height = nbgl_getFontLineHeight(textArea->fontId); - // set this new text area as child of the main container - addObjectToLayout(layoutInt,(nbgl_obj_t*)textArea); - } - - // create text area - textArea = (nbgl_text_area_t*)nbgl_objPoolGet(TEXT_AREA, layoutInt->layer); - textArea->textColor = grayedOut ? LIGHT_GRAY:BLACK; - textArea->text = text; - textArea->textAlignment = MID_LEFT; - textArea->fontId = BAGL_FONT_INTER_MEDIUM_32px_1bpp; - textArea->obj.alignmentMarginY = 12; - textArea->obj.alignTo = (nbgl_obj_t*)line; - textArea->obj.alignment = TOP_MIDDLE; - if (numbered) { - textArea->obj.area.width = line->obj.area.width - 2*50; - } - else { - textArea->obj.area.width = line->obj.area.width; - } - textArea->obj.area.height = nbgl_getFontLineHeight(textArea->fontId); - textArea->autoHideLongLine = true; - - obj = addCallbackObj(layoutInt,(nbgl_obj_t*)textArea,token,NBGL_NO_TUNE); - if (obj == NULL) - return -1; - textArea->token = token; - textArea->obj.touchMask = (1<container->nbChildren-1); + textArea->obj.alignTo = (nbgl_obj_t *) line; + textArea->obj.alignment = TOP_MIDDLE; + if (numbered) { + textArea->obj.area.width = line->obj.area.width - 2 * 50; + } + else { + textArea->obj.area.width = line->obj.area.width; + } + textArea->obj.area.height = nbgl_getFontLineHeight(textArea->fontId); + textArea->autoHideLongLine = true; + + obj = addCallbackObj(layoutInt, (nbgl_obj_t *) textArea, token, NBGL_NO_TUNE); + if (obj == NULL) { + return -1; + } + textArea->token = token; + textArea->obj.touchMask = (1 << TOUCHED); + // set this new text area as child of the container + addObjectToLayout(layoutInt, (nbgl_obj_t *) textArea); + + // return index of text area to be modified later on + return (layoutInt->container->nbChildren - 1); } /** @@ -2292,37 +2511,44 @@ int nbgl_layoutAddEnteredText(nbgl_layout_t *layout, bool numbered, uint8_t numb * @return <0 if error, 0 if OK with text fitting the area, 1 of 0K with text * not fitting the area */ -int nbgl_layoutUpdateEnteredText(nbgl_layout_t *layout, uint8_t index, bool numbered, uint8_t number, const char *text, bool grayedOut) { - nbgl_layoutInternal_t *layoutInt = (nbgl_layoutInternal_t *)layout; - nbgl_text_area_t *textArea; - - LOG_DEBUG(LAYOUT_LOGGER,"nbgl_layoutUpdateEnteredText():\n"); - if (layout == NULL) - return -1; - - // update main text area - textArea = (nbgl_text_area_t*)layoutInt->container->children[index]; - if ((textArea == NULL) || (textArea->obj.type != TEXT_AREA)) { - return -1; - } - textArea->text = text; - textArea->textColor = grayedOut ? LIGHT_GRAY : BLACK; - textArea->textAlignment = MID_LEFT; - nbgl_redrawObject((nbgl_obj_t*)textArea,NULL,false); - - // update number text area - if (numbered) { - // it is the previously created object - textArea = (nbgl_text_area_t*)layoutInt->container->children[index-1]; - snprintf(numText,sizeof(numText),"%d.",number); - textArea->text = numText; - nbgl_redrawObject((nbgl_obj_t*)textArea,NULL,false); - } - // if the text doesn't fit, indicate it by returning 1 instead of 0, for different refresh - if (nbgl_getSingleLineTextWidth(textArea->fontId, text) > textArea->obj.area.width) { - return 1; - } - return 0; +int nbgl_layoutUpdateEnteredText(nbgl_layout_t *layout, + uint8_t index, + bool numbered, + uint8_t number, + const char *text, + bool grayedOut) +{ + nbgl_layoutInternal_t *layoutInt = (nbgl_layoutInternal_t *) layout; + nbgl_text_area_t *textArea; + + LOG_DEBUG(LAYOUT_LOGGER, "nbgl_layoutUpdateEnteredText():\n"); + if (layout == NULL) { + return -1; + } + + // update main text area + textArea = (nbgl_text_area_t *) layoutInt->container->children[index]; + if ((textArea == NULL) || (textArea->obj.type != TEXT_AREA)) { + return -1; + } + textArea->text = text; + textArea->textColor = grayedOut ? LIGHT_GRAY : BLACK; + textArea->textAlignment = MID_LEFT; + nbgl_redrawObject((nbgl_obj_t *) textArea, NULL, false); + + // update number text area + if (numbered) { + // it is the previously created object + textArea = (nbgl_text_area_t *) layoutInt->container->children[index - 1]; + snprintf(numText, sizeof(numText), "%d.", number); + textArea->text = numText; + nbgl_redrawObject((nbgl_obj_t *) textArea, NULL, false); + } + // if the text doesn't fit, indicate it by returning 1 instead of 0, for different refresh + if (nbgl_getSingleLineTextWidth(textArea->fontId, text) > textArea->obj.area.width) { + return 1; + } + return 0; } /** @@ -2335,47 +2561,55 @@ int nbgl_layoutUpdateEnteredText(nbgl_layout_t *layout, uint8_t index, bool numb * @param tuneId tune to play when button is pressed * @return >= 0 if OK */ -int nbgl_layoutAddConfirmationButton(nbgl_layout_t *layout, bool active, const char *text, int token, tune_index_e tuneId) { - layoutObj_t *obj; - nbgl_button_t *button; - nbgl_layoutInternal_t *layoutInt = (nbgl_layoutInternal_t *)layout; - - LOG_DEBUG(LAYOUT_LOGGER,"nbgl_layoutAddConfirmationButton():\n"); - if (layout == NULL) - return -1; - - button = (nbgl_button_t *)nbgl_objPoolGet(BUTTON,layoutInt->layer); - obj = addCallbackObj(layoutInt,(nbgl_obj_t*)button,token,tuneId); - if (obj == NULL) - return -1; - - button->obj.alignmentMarginY = BORDER_MARGIN; - button->obj.alignment = TOP_MIDDLE; - button->foregroundColor = WHITE; - if (active) { - button->innerColor = BLACK; - button->borderColor = BLACK; - button->obj.touchMask = (1 << TOUCHED); - } - else { - button->borderColor = LIGHT_GRAY; - button->innerColor = LIGHT_GRAY; - } - button->text = PIC(text); - button->fontId = BAGL_FONT_INTER_SEMIBOLD_24px_1bpp; - button->obj.area.width = AVAILABLE_WIDTH; - button->obj.area.height = BUTTON_DIAMETER; - button->radius = BUTTON_RADIUS; - button->obj.alignTo = layoutInt->container->children[layoutInt->container->nbChildren-1]; - // set this new button as child of the container - addObjectToLayout(layoutInt,(nbgl_obj_t*)button); - - // return index of button to be modified later on - return (layoutInt->container->nbChildren-1); +int nbgl_layoutAddConfirmationButton(nbgl_layout_t *layout, + bool active, + const char *text, + int token, + tune_index_e tuneId) +{ + layoutObj_t *obj; + nbgl_button_t *button; + nbgl_layoutInternal_t *layoutInt = (nbgl_layoutInternal_t *) layout; + + LOG_DEBUG(LAYOUT_LOGGER, "nbgl_layoutAddConfirmationButton():\n"); + if (layout == NULL) { + return -1; + } + + button = (nbgl_button_t *) nbgl_objPoolGet(BUTTON, layoutInt->layer); + obj = addCallbackObj(layoutInt, (nbgl_obj_t *) button, token, tuneId); + if (obj == NULL) { + return -1; + } + + button->obj.alignmentMarginY = BORDER_MARGIN; + button->obj.alignment = TOP_MIDDLE; + button->foregroundColor = WHITE; + if (active) { + button->innerColor = BLACK; + button->borderColor = BLACK; + button->obj.touchMask = (1 << TOUCHED); + } + else { + button->borderColor = LIGHT_GRAY; + button->innerColor = LIGHT_GRAY; + } + button->text = PIC(text); + button->fontId = BAGL_FONT_INTER_SEMIBOLD_24px_1bpp; + button->obj.area.width = AVAILABLE_WIDTH; + button->obj.area.height = BUTTON_DIAMETER; + button->radius = BUTTON_RADIUS; + button->obj.alignTo = layoutInt->container->children[layoutInt->container->nbChildren - 1]; + // set this new button as child of the container + addObjectToLayout(layoutInt, (nbgl_obj_t *) button); + + // return index of button to be modified later on + return (layoutInt->container->nbChildren - 1); } /** - * @brief Updates an existing black full width confirmation button on top of the previously added keyboard. + * @brief Updates an existing black full width confirmation button on top of the previously added +keyboard. * * @param layout the current layout * @param index returned value of @ref nbgl_layoutAddConfirmationButton() @@ -2383,34 +2617,39 @@ int nbgl_layoutAddConfirmationButton(nbgl_layout_t *layout, bool active, const c * @param text text of the button = * @return >= 0 if OK */ -int nbgl_layoutUpdateConfirmationButton(nbgl_layout_t *layout, uint8_t index, bool active, const char *text) { - nbgl_layoutInternal_t *layoutInt = (nbgl_layoutInternal_t *)layout; - nbgl_button_t *button; - - LOG_DEBUG(LAYOUT_LOGGER,"nbgl_layoutUpdateConfirmationButton():\n"); - if (layout == NULL) - return -1; - - // update main text area - button = (nbgl_button_t*)layoutInt->container->children[index]; - if ((button == NULL) || (button->obj.type != BUTTON)) { - return -1; - } - button->text = text; - - if (active) { - button->innerColor = BLACK; - button->borderColor = BLACK; - button->obj.touchMask = (1 << TOUCHED); - } - else { - button->borderColor = LIGHT_GRAY; - button->innerColor = LIGHT_GRAY; - } - nbgl_redrawObject((nbgl_obj_t*)button,NULL,false); - return 0; +int nbgl_layoutUpdateConfirmationButton(nbgl_layout_t *layout, + uint8_t index, + bool active, + const char *text) +{ + nbgl_layoutInternal_t *layoutInt = (nbgl_layoutInternal_t *) layout; + nbgl_button_t *button; + + LOG_DEBUG(LAYOUT_LOGGER, "nbgl_layoutUpdateConfirmationButton():\n"); + if (layout == NULL) { + return -1; + } + + // update main text area + button = (nbgl_button_t *) layoutInt->container->children[index]; + if ((button == NULL) || (button->obj.type != BUTTON)) { + return -1; + } + button->text = text; + + if (active) { + button->innerColor = BLACK; + button->borderColor = BLACK; + button->obj.touchMask = (1 << TOUCHED); + } + else { + button->borderColor = LIGHT_GRAY; + button->innerColor = LIGHT_GRAY; + } + nbgl_redrawObject((nbgl_obj_t *) button, NULL, false); + return 0; } -#endif // NBGL_KEYBOARD +#endif // NBGL_KEYBOARD #ifdef NBGL_KEYPAD /** @@ -2423,30 +2662,32 @@ int nbgl_layoutUpdateConfirmationButton(nbgl_layout_t *layout, uint8_t index, bo * @param shuffled if set to true, digits are shuffled in keypad * @return the index of keypad, to use in @ref nbgl_layoutUpdateKeypad() */ -int nbgl_layoutAddKeypad(nbgl_layout_t *layout, keyboardCallback_t callback, bool shuffled) { - nbgl_layoutInternal_t *layoutInt = (nbgl_layoutInternal_t *)layout; - nbgl_keypad_t *keypad; - - LOG_DEBUG(LAYOUT_LOGGER,"nbgl_layoutAddKeypad():\n"); - if (layout == NULL) - return -1; - - // create keypad - keypad = (nbgl_keypad_t*)nbgl_objPoolGet(KEYPAD, layoutInt->layer); - keypad->obj.alignmentMarginY = 0; - keypad->obj.alignment = BOTTOM_MIDDLE; - keypad->obj.alignTo = NULL; - keypad->borderColor = LIGHT_GRAY; - keypad->callback = PIC(callback); - keypad->enableDigits = true; - keypad->enableBackspace = false; - keypad->enableValidate = false; - keypad->shuffled = shuffled; - // set this new keypad as child of the container - addObjectToLayout(layoutInt,(nbgl_obj_t*)keypad); - - // return index of keypad to be modified later on - return (layoutInt->container->nbChildren-1); +int nbgl_layoutAddKeypad(nbgl_layout_t *layout, keyboardCallback_t callback, bool shuffled) +{ + nbgl_layoutInternal_t *layoutInt = (nbgl_layoutInternal_t *) layout; + nbgl_keypad_t *keypad; + + LOG_DEBUG(LAYOUT_LOGGER, "nbgl_layoutAddKeypad():\n"); + if (layout == NULL) { + return -1; + } + + // create keypad + keypad = (nbgl_keypad_t *) nbgl_objPoolGet(KEYPAD, layoutInt->layer); + keypad->obj.alignmentMarginY = 0; + keypad->obj.alignment = BOTTOM_MIDDLE; + keypad->obj.alignTo = NULL; + keypad->borderColor = LIGHT_GRAY; + keypad->callback = PIC(callback); + keypad->enableDigits = true; + keypad->enableBackspace = false; + keypad->enableValidate = false; + keypad->shuffled = shuffled; + // set this new keypad as child of the container + addObjectToLayout(layoutInt, (nbgl_obj_t *) keypad); + + // return index of keypad to be modified later on + return (layoutInt->container->nbChildren - 1); } /** @@ -2459,100 +2700,116 @@ int nbgl_layoutAddKeypad(nbgl_layout_t *layout, keyboardCallback_t callback, boo * @param enableDigits if true, enable all digit keys * @return >=0 if OK */ -int nbgl_layoutUpdateKeypad(nbgl_layout_t *layout, uint8_t index, bool enableValidate, bool enableBackspace, bool enableDigits) { - nbgl_layoutInternal_t *layoutInt = (nbgl_layoutInternal_t *)layout; - nbgl_keypad_t *keypad; - - LOG_DEBUG(LAYOUT_LOGGER,"nbgl_layoutUpdateKeypad(): enableValidate = %d, enableBackspace = %d\n",enableValidate,enableBackspace); - if (layout == NULL) - return -1; - - // get existing keypad - keypad = (nbgl_keypad_t*)layoutInt->container->children[index]; - if ((keypad == NULL) || (keypad->obj.type != KEYPAD)) { - return -1; - } - keypad->enableValidate = enableValidate; - keypad->enableBackspace = enableBackspace; - keypad->enableDigits = enableDigits; - - nbgl_redrawObject((nbgl_obj_t*)keypad,NULL,false); - - return 0; +int nbgl_layoutUpdateKeypad(nbgl_layout_t *layout, + uint8_t index, + bool enableValidate, + bool enableBackspace, + bool enableDigits) +{ + nbgl_layoutInternal_t *layoutInt = (nbgl_layoutInternal_t *) layout; + nbgl_keypad_t *keypad; + + LOG_DEBUG(LAYOUT_LOGGER, + "nbgl_layoutUpdateKeypad(): enableValidate = %d, enableBackspace = %d\n", + enableValidate, + enableBackspace); + if (layout == NULL) { + return -1; + } + + // get existing keypad + keypad = (nbgl_keypad_t *) layoutInt->container->children[index]; + if ((keypad == NULL) || (keypad->obj.type != KEYPAD)) { + return -1; + } + keypad->enableValidate = enableValidate; + keypad->enableBackspace = enableBackspace; + keypad->enableDigits = enableDigits; + + nbgl_redrawObject((nbgl_obj_t *) keypad, NULL, false); + + return 0; } /** - * @brief Adds a placeholder for hidden digits on top of a keypad, to represent the entered digits, as full circles - * The placeholder is "underligned" with a thin horizontal line of the expected full length + * @brief Adds a placeholder for hidden digits on top of a keypad, to represent the entered digits, + * as full circles The placeholder is "underligned" with a thin horizontal line of the expected full + * length * - * @note It must be the last added object, after potential back key, title, and keypad. Vertical positions of title and hidden digits will be computed here + * @note It must be the last added object, after potential back key, title, and keypad. Vertical + * positions of title and hidden digits will be computed here * * @param layout the current layout * @param nbDigits number of digits to be displayed * @return the index of digits set, to use in @ref nbgl_layoutUpdateHiddenDigits() */ -int nbgl_layoutAddHiddenDigits(nbgl_layout_t *layout, uint8_t nbDigits) { - nbgl_layoutInternal_t *layoutInt = (nbgl_layoutInternal_t *)layout; - nbgl_container_t *container; - nbgl_line_t *line; - - LOG_DEBUG(LAYOUT_LOGGER,"nbgl_layoutAddHiddenDigits():\n"); - if (layout == NULL) - return -1; - - // create a container, invisible or bordered - container = (nbgl_container_t*)nbgl_objPoolGet(CONTAINER,layoutInt->layer); - container->nbChildren = nbDigits+1; // +1 for the line - container->children = nbgl_containerPoolGet(container->nbChildren, layoutInt->layer); - // 12 pixels between each icon (knowing that the effective round are 18px large and the icon 24px) - container->obj.area.width = nbDigits*C_round_24px.width + (nbDigits+1)*12; - container->obj.area.height = 48; - // distance from digits to title is fixed to 20 px, except if title is more than 1 line and a back key is present - if ((layoutInt->container->nbChildren != 3) || (layoutInt->container->children[1]->area.height == 32)) { - container->obj.alignmentMarginY = 20; - } - else { - container->obj.alignmentMarginY = 12; - } - - // item N-2 is the title - container->obj.alignTo = layoutInt->container->children[layoutInt->container->nbChildren-2]; - container->obj.alignment = BOTTOM_MIDDLE; - - // set this new container as child of the main container - addObjectToLayout(layoutInt,(nbgl_obj_t*)container); - - // create children of the container, as images (empty circles) - nbgl_objPoolGetArray(IMAGE,nbDigits,layoutInt->layer,(nbgl_obj_t**)container->children); - for (int i=0;ichildren[i]; - image->buffer = &C_round_24px; - image->foregroundColor = WHITE; - image->obj.alignmentMarginX = 12; - if (i>0) { - image->obj.alignment = MID_RIGHT; - image->obj.alignTo = (nbgl_obj_t*)container->children[i-1]; +int nbgl_layoutAddHiddenDigits(nbgl_layout_t *layout, uint8_t nbDigits) +{ + nbgl_layoutInternal_t *layoutInt = (nbgl_layoutInternal_t *) layout; + nbgl_container_t *container; + nbgl_line_t *line; + + LOG_DEBUG(LAYOUT_LOGGER, "nbgl_layoutAddHiddenDigits():\n"); + if (layout == NULL) { + return -1; + } + + // create a container, invisible or bordered + container = (nbgl_container_t *) nbgl_objPoolGet(CONTAINER, layoutInt->layer); + container->nbChildren = nbDigits + 1; // +1 for the line + container->children = nbgl_containerPoolGet(container->nbChildren, layoutInt->layer); + // 12 pixels between each icon (knowing that the effective round are 18px large and the icon + // 24px) + container->obj.area.width = nbDigits * C_round_24px.width + (nbDigits + 1) * 12; + container->obj.area.height = 48; + // distance from digits to title is fixed to 20 px, except if title is more than 1 line and a + // back key is present + if ((layoutInt->container->nbChildren != 3) + || (layoutInt->container->children[1]->area.height == 32)) { + container->obj.alignmentMarginY = 20; } else { - image->obj.alignment = NO_ALIGNMENT; - image->obj.alignmentMarginY = (container->obj.area.height - C_round_24px.width)/2; - } - } - // create gray line - line = (nbgl_line_t*)nbgl_objPoolGet(LINE, layoutInt->layer); - line->lineColor = LIGHT_GRAY; - line->obj.alignmentMarginY = 0; - line->obj.alignTo = NULL; - line->obj.alignment = BOTTOM_MIDDLE; - line->obj.area.width = container->obj.area.width; - line->obj.area.height = 4; - line->direction = HORIZONTAL; - line->thickness = 2; - line->offset = 2; - container->children[nbDigits] = (nbgl_obj_t*)line; - - // return index of keypad to be modified later on - return (layoutInt->container->nbChildren-1); + container->obj.alignmentMarginY = 12; + } + + // item N-2 is the title + container->obj.alignTo = layoutInt->container->children[layoutInt->container->nbChildren - 2]; + container->obj.alignment = BOTTOM_MIDDLE; + + // set this new container as child of the main container + addObjectToLayout(layoutInt, (nbgl_obj_t *) container); + + // create children of the container, as images (empty circles) + nbgl_objPoolGetArray(IMAGE, nbDigits, layoutInt->layer, (nbgl_obj_t **) container->children); + for (int i = 0; i < nbDigits; i++) { + nbgl_image_t *image = (nbgl_image_t *) container->children[i]; + image->buffer = &C_round_24px; + image->foregroundColor = WHITE; + image->obj.alignmentMarginX = 12; + if (i > 0) { + image->obj.alignment = MID_RIGHT; + image->obj.alignTo = (nbgl_obj_t *) container->children[i - 1]; + } + else { + image->obj.alignment = NO_ALIGNMENT; + image->obj.alignmentMarginY = (container->obj.area.height - C_round_24px.width) / 2; + } + } + // create gray line + line = (nbgl_line_t *) nbgl_objPoolGet(LINE, layoutInt->layer); + line->lineColor = LIGHT_GRAY; + line->obj.alignmentMarginY = 0; + line->obj.alignTo = NULL; + line->obj.alignment = BOTTOM_MIDDLE; + line->obj.area.width = container->obj.area.width; + line->obj.area.height = 4; + line->direction = HORIZONTAL; + line->thickness = 2; + line->offset = 2; + container->children[nbDigits] = (nbgl_obj_t *) line; + + // return index of keypad to be modified later on + return (layoutInt->container->nbChildren - 1); } /** @@ -2563,59 +2820,61 @@ int nbgl_layoutAddHiddenDigits(nbgl_layout_t *layout, uint8_t nbDigits) { * @param nbActive number of "active" digits (represented by discs instead of circles) * @return >=0 if OK */ -int nbgl_layoutUpdateHiddenDigits(nbgl_layout_t *layout, uint8_t index, uint8_t nbActive) { - nbgl_layoutInternal_t *layoutInt = (nbgl_layoutInternal_t *)layout; - nbgl_container_t *container; - nbgl_image_t* image; - - LOG_DEBUG(LAYOUT_LOGGER,"nbgl_layoutUpdateHiddenDigits(): nbActive = %d\n",nbActive); - if (layout == NULL) - return -1; - - // get container - container = (nbgl_container_t*)layoutInt->container->children[index]; - // sanity check - if ((container == NULL) || (container->obj.type != CONTAINER)) { - return -1; - } - if (nbActive > container->nbChildren) { - return -1; - } - if (nbActive == 0) { - // deactivate the first digit - image = (nbgl_image_t*)container->children[0]; - if ((image == NULL) || (image->obj.type != IMAGE)) { - return -1; - } - image->foregroundColor = WHITE; - } - else { - image = (nbgl_image_t*)container->children[nbActive-1]; - if ((image == NULL) || (image->obj.type != IMAGE)) { - return -1; - } - // if the last "active" is already active, it means that we are decreasing the number of active - // otherwise we are increasing it - if (image->foregroundColor == BLACK) { - // all digits are already active - if (nbActive == container->nbChildren) { - return 0; - } - // deactivate the next digit - image = (nbgl_image_t*)container->children[nbActive]; - image->foregroundColor = WHITE; +int nbgl_layoutUpdateHiddenDigits(nbgl_layout_t *layout, uint8_t index, uint8_t nbActive) +{ + nbgl_layoutInternal_t *layoutInt = (nbgl_layoutInternal_t *) layout; + nbgl_container_t *container; + nbgl_image_t *image; + + LOG_DEBUG(LAYOUT_LOGGER, "nbgl_layoutUpdateHiddenDigits(): nbActive = %d\n", nbActive); + if (layout == NULL) { + return -1; + } + + // get container + container = (nbgl_container_t *) layoutInt->container->children[index]; + // sanity check + if ((container == NULL) || (container->obj.type != CONTAINER)) { + return -1; + } + if (nbActive > container->nbChildren) { + return -1; + } + if (nbActive == 0) { + // deactivate the first digit + image = (nbgl_image_t *) container->children[0]; + if ((image == NULL) || (image->obj.type != IMAGE)) { + return -1; + } + image->foregroundColor = WHITE; } else { - image->buffer = &C_round_24px; - image->foregroundColor = BLACK; + image = (nbgl_image_t *) container->children[nbActive - 1]; + if ((image == NULL) || (image->obj.type != IMAGE)) { + return -1; + } + // if the last "active" is already active, it means that we are decreasing the number of + // active otherwise we are increasing it + if (image->foregroundColor == BLACK) { + // all digits are already active + if (nbActive == container->nbChildren) { + return 0; + } + // deactivate the next digit + image = (nbgl_image_t *) container->children[nbActive]; + image->foregroundColor = WHITE; + } + else { + image->buffer = &C_round_24px; + image->foregroundColor = BLACK; + } } - } - nbgl_redrawObject((nbgl_obj_t*)image,NULL,false); + nbgl_redrawObject((nbgl_obj_t *) image, NULL, false); - return 0; + return 0; } -#endif // NBGL_KEYPAD +#endif // NBGL_KEYPAD /** * @brief Applies given layout. The screen will be redrawn @@ -2623,25 +2882,30 @@ int nbgl_layoutUpdateHiddenDigits(nbgl_layout_t *layout, uint8_t index, uint8_t * @param layoutParam layout to redraw * @return a pointer to the corresponding layout */ -int nbgl_layoutDraw(nbgl_layout_t *layoutParam) { - nbgl_layoutInternal_t *layout = (nbgl_layoutInternal_t *)layoutParam; +int nbgl_layoutDraw(nbgl_layout_t *layoutParam) +{ + nbgl_layoutInternal_t *layout = (nbgl_layoutInternal_t *) layoutParam; - if (layout == NULL) - return -1; - LOG_DEBUG(LAYOUT_LOGGER,"nbgl_layoutDraw(): container.nbChildren =%d, layout->nbChildren = %d\n",layout->container->nbChildren,layout->nbChildren); - if (layout->tapText) { - // set this new container as child of main container - addObjectToLayout(layout,(nbgl_obj_t*)layout->tapText); - } - if (layout->withLeftBorder == true) { - // draw now the line - nbgl_line_t *line = createLeftVerticalLine(layout->layer); - layout->children[layout->nbChildren] = (nbgl_obj_t*)line; - layout->nbChildren++; - } - nbgl_screenRedraw(); + if (layout == NULL) { + return -1; + } + LOG_DEBUG(LAYOUT_LOGGER, + "nbgl_layoutDraw(): container.nbChildren =%d, layout->nbChildren = %d\n", + layout->container->nbChildren, + layout->nbChildren); + if (layout->tapText) { + // set this new container as child of main container + addObjectToLayout(layout, (nbgl_obj_t *) layout->tapText); + } + if (layout->withLeftBorder == true) { + // draw now the line + nbgl_line_t *line = createLeftVerticalLine(layout->layer); + layout->children[layout->nbChildren] = (nbgl_obj_t *) line; + layout->nbChildren++; + } + nbgl_screenRedraw(); - return 0; + return 0; } /** @@ -2650,15 +2914,17 @@ int nbgl_layoutDraw(nbgl_layout_t *layoutParam) { * @param layoutParam layout to release * @return >= 0 if OK */ -int nbgl_layoutRelease(nbgl_layout_t *layoutParam) { - nbgl_layoutInternal_t *layout = (nbgl_layoutInternal_t *)layoutParam; - LOG_DEBUG(PAGE_LOGGER,"nbgl_layoutRelease(): \n"); - if (layout == NULL) - return -1; - // if modal - if (layout->modal) { - nbgl_screenPop(layout->layer); - } - layout->nbChildren = 0; - return 0; +int nbgl_layoutRelease(nbgl_layout_t *layoutParam) +{ + nbgl_layoutInternal_t *layout = (nbgl_layoutInternal_t *) layoutParam; + LOG_DEBUG(PAGE_LOGGER, "nbgl_layoutRelease(): \n"); + if (layout == NULL) { + return -1; + } + // if modal + if (layout->modal) { + nbgl_screenPop(layout->layer); + } + layout->nbChildren = 0; + return 0; } diff --git a/lib_nbgl/src/nbgl_navigation.c b/lib_nbgl/src/nbgl_navigation.c index e491da2d8..32887760d 100644 --- a/lib_nbgl/src/nbgl_navigation.c +++ b/lib_nbgl/src/nbgl_navigation.c @@ -18,15 +18,14 @@ *********************/ #define INTERNAL_SMALL_MARGIN 8 - /********************** * TYPEDEFS **********************/ enum { - EXIT_BUTTON_INDEX = 0, - PREVIOUS_PAGE_INDEX, - NEXT_PAGE_INDEX, - NB_MAX_CHILDREN + EXIT_BUTTON_INDEX = 0, + PREVIOUS_PAGE_INDEX, + NEXT_PAGE_INDEX, + NB_MAX_CHILDREN }; /********************** @@ -41,12 +40,13 @@ enum { * STATIC PROTOTYPES **********************/ -static void configButtons(nbgl_container_t *navContainer, uint8_t navNbPages, uint8_t navActivePage) { - nbgl_button_t *buttonPrevious = (nbgl_button_t *)navContainer->children[PREVIOUS_PAGE_INDEX]; - nbgl_button_t *buttonNext = (nbgl_button_t *)navContainer->children[NEXT_PAGE_INDEX]; +static void configButtons(nbgl_container_t *navContainer, uint8_t navNbPages, uint8_t navActivePage) +{ + nbgl_button_t *buttonPrevious = (nbgl_button_t *) navContainer->children[PREVIOUS_PAGE_INDEX]; + nbgl_button_t *buttonNext = (nbgl_button_t *) navContainer->children[NEXT_PAGE_INDEX]; - buttonPrevious->foregroundColor = (navActivePage == 0) ? LIGHT_GRAY : BLACK; - buttonNext->foregroundColor = (navActivePage == (navNbPages-1)) ? LIGHT_GRAY : BLACK; + buttonPrevious->foregroundColor = (navActivePage == 0) ? LIGHT_GRAY : BLACK; + buttonNext->foregroundColor = (navActivePage == (navNbPages - 1)) ? LIGHT_GRAY : BLACK; } /********************** @@ -62,38 +62,43 @@ static void configButtons(nbgl_container_t *navContainer, uint8_t navNbPages, ui * @param activePage current active page * @return true if actually navigated (page change) */ -bool nbgl_navigationCallback(nbgl_obj_t *obj, nbgl_touchType_t eventType, uint8_t nbPages, uint8_t *activePage) { - nbgl_container_t *navContainer; +bool nbgl_navigationCallback(nbgl_obj_t *obj, + nbgl_touchType_t eventType, + uint8_t nbPages, + uint8_t *activePage) +{ + nbgl_container_t *navContainer; + + if (eventType != TOUCHED) { + return false; + } + navContainer = (nbgl_container_t *) obj->parent; - if (eventType != TOUCHED) { - return false; - } - navContainer = (nbgl_container_t *)obj->parent; - - if (obj == navContainer->children[EXIT_BUTTON_INDEX]) { - // fake page when Quit button is touched - *activePage = EXIT_PAGE; - return true; - } - else if (obj == navContainer->children[PREVIOUS_PAGE_INDEX]) { - if (*activePage > 0) { - *activePage = *activePage - 1; - configButtons(navContainer, nbPages, *activePage); - return true; + if (obj == navContainer->children[EXIT_BUTTON_INDEX]) { + // fake page when Quit button is touched + *activePage = EXIT_PAGE; + return true; + } + else if (obj == navContainer->children[PREVIOUS_PAGE_INDEX]) { + if (*activePage > 0) { + *activePage = *activePage - 1; + configButtons(navContainer, nbPages, *activePage); + return true; + } } - } - else if (obj == navContainer->children[NEXT_PAGE_INDEX]) { - if (*activePage < (nbPages-1)) { - *activePage = *activePage + 1; - configButtons(navContainer, nbPages, *activePage); - return true; + else if (obj == navContainer->children[NEXT_PAGE_INDEX]) { + if (*activePage < (nbPages - 1)) { + *activePage = *activePage + 1; + configButtons(navContainer, nbPages, *activePage); + return true; + } } - } - return false; + return false; } /** - * @brief This function creates a full navigation bar "object", with buttons and returns it as a container + * @brief This function creates a full navigation bar "object", with buttons and returns it as a + * container * * @param nbPages max number of pages for navigation (if < 2, no navigation keys) * @param activePage active page at start-up in [0-(nbPages-1)] @@ -102,84 +107,93 @@ bool nbgl_navigationCallback(nbgl_obj_t *obj, nbgl_touchType_t eventType, uint8_ * * @return the created navigation bar container object */ -nbgl_container_t *nbgl_navigationPopulate(uint8_t nbPages, uint8_t activePage, bool withExitKey, uint8_t layer) { - nbgl_button_t *button; - nbgl_container_t *navContainer; - - navContainer = (nbgl_container_t *)nbgl_objPoolGet(CONTAINER, layer); - navContainer->obj.area.width = SCREEN_WIDTH - 2*BORDER_MARGIN; - navContainer->obj.area.height = BUTTON_DIAMETER+2*BORDER_MARGIN; - navContainer->layout = HORIZONTAL ; - navContainer->nbChildren = NB_MAX_CHILDREN; - navContainer->children = (nbgl_obj_t**)nbgl_containerPoolGet(navContainer->nbChildren, layer); - navContainer->obj.alignmentMarginX = 0; - navContainer->obj.alignmentMarginY = 0; - navContainer->obj.alignment = NO_ALIGNMENT; - - if (withExitKey) { - button = (nbgl_button_t*)nbgl_objPoolGet(BUTTON,layer); - button->innerColor = WHITE; - button->borderColor = LIGHT_GRAY; - button->obj.area.width = BUTTON_DIAMETER; - button->obj.area.height = BUTTON_DIAMETER; - button->radius = BUTTON_RADIUS; - button->text = NULL; - button->icon = &C_cross32px; - button->obj.alignmentMarginX = 0; - button->obj.alignmentMarginY = 0; - - button->obj.alignment = (nbPages > 1) ? MID_LEFT:CENTER; - button->obj.alignTo = NULL; - button->obj.touchMask = (1<children[EXIT_BUTTON_INDEX] = (nbgl_obj_t*)button; - } - if (nbPages > 1) { - button = (nbgl_button_t*)nbgl_objPoolGet(BUTTON,layer); - button->innerColor = WHITE; - button->borderColor = LIGHT_GRAY; - button->obj.area.width = (SCREEN_WIDTH - (2*BORDER_MARGIN+2*INTERNAL_SMALL_MARGIN+BUTTON_DIAMETER))/2; - if (!withExitKey) - button->obj.area.width += BUTTON_DIAMETER/2; - button->obj.area.height = BUTTON_DIAMETER; - button->radius = BUTTON_RADIUS; - button->text = NULL; - button->icon = &C_leftArrow32px; - button->obj.alignmentMarginY = 0; +nbgl_container_t *nbgl_navigationPopulate(uint8_t nbPages, + uint8_t activePage, + bool withExitKey, + uint8_t layer) +{ + nbgl_button_t *button; + nbgl_container_t *navContainer; + + navContainer = (nbgl_container_t *) nbgl_objPoolGet(CONTAINER, layer); + navContainer->obj.area.width = SCREEN_WIDTH - 2 * BORDER_MARGIN; + navContainer->obj.area.height = BUTTON_DIAMETER + 2 * BORDER_MARGIN; + navContainer->layout = HORIZONTAL; + navContainer->nbChildren = NB_MAX_CHILDREN; + navContainer->children = (nbgl_obj_t **) nbgl_containerPoolGet(navContainer->nbChildren, layer); + navContainer->obj.alignmentMarginX = 0; + navContainer->obj.alignmentMarginY = 0; + navContainer->obj.alignment = NO_ALIGNMENT; + if (withExitKey) { - button->obj.alignmentMarginX = INTERNAL_SMALL_MARGIN; - button->obj.alignment = MID_RIGHT; - button->obj.alignTo = navContainer->children[EXIT_BUTTON_INDEX]; + button = (nbgl_button_t *) nbgl_objPoolGet(BUTTON, layer); + button->innerColor = WHITE; + button->borderColor = LIGHT_GRAY; + button->obj.area.width = BUTTON_DIAMETER; + button->obj.area.height = BUTTON_DIAMETER; + button->radius = BUTTON_RADIUS; + button->text = NULL; + button->icon = &C_cross32px; + button->obj.alignmentMarginX = 0; + button->obj.alignmentMarginY = 0; + + button->obj.alignment = (nbPages > 1) ? MID_LEFT : CENTER; + button->obj.alignTo = NULL; + button->obj.touchMask = (1 << TOUCHED); + navContainer->children[EXIT_BUTTON_INDEX] = (nbgl_obj_t *) button; } - else { - button->obj.alignmentMarginX = 0; - button->obj.alignment = MID_LEFT; - button->obj.alignTo = NULL; - + if (nbPages > 1) { + button = (nbgl_button_t *) nbgl_objPoolGet(BUTTON, layer); + button->innerColor = WHITE; + button->borderColor = LIGHT_GRAY; + button->obj.area.width + = (SCREEN_WIDTH - (2 * BORDER_MARGIN + 2 * INTERNAL_SMALL_MARGIN + BUTTON_DIAMETER)) + / 2; + if (!withExitKey) { + button->obj.area.width += BUTTON_DIAMETER / 2; + } + button->obj.area.height = BUTTON_DIAMETER; + button->radius = BUTTON_RADIUS; + button->text = NULL; + button->icon = &C_leftArrow32px; + button->obj.alignmentMarginY = 0; + if (withExitKey) { + button->obj.alignmentMarginX = INTERNAL_SMALL_MARGIN; + button->obj.alignment = MID_RIGHT; + button->obj.alignTo = navContainer->children[EXIT_BUTTON_INDEX]; + } + else { + button->obj.alignmentMarginX = 0; + button->obj.alignment = MID_LEFT; + button->obj.alignTo = NULL; + } + button->obj.touchMask = (1 << TOUCHED); + navContainer->children[PREVIOUS_PAGE_INDEX] = (nbgl_obj_t *) button; + + // create next page button + button = (nbgl_button_t *) nbgl_objPoolGet(BUTTON, layer); + button->innerColor = WHITE; + button->borderColor = LIGHT_GRAY; + button->foregroundColor = BLACK; + button->obj.area.width + = (SCREEN_WIDTH - (2 * BORDER_MARGIN + 2 * INTERNAL_SMALL_MARGIN + BUTTON_DIAMETER)) + / 2; + if (!withExitKey) { + button->obj.area.width += BUTTON_DIAMETER / 2; + } + button->obj.area.height = BUTTON_DIAMETER; + button->radius = BUTTON_RADIUS; + button->text = NULL; + button->icon = &C_rightArrow32px; + button->obj.alignmentMarginX = INTERNAL_SMALL_MARGIN; + button->obj.alignmentMarginY = 0; + button->obj.alignment = MID_RIGHT; + button->obj.alignTo = navContainer->children[PREVIOUS_PAGE_INDEX]; + button->obj.touchMask = (1 << TOUCHED); + navContainer->children[NEXT_PAGE_INDEX] = (nbgl_obj_t *) button; + + configButtons(navContainer, nbPages, activePage); } - button->obj.touchMask = (1<children[PREVIOUS_PAGE_INDEX] = (nbgl_obj_t*)button; - - // create next page button - button = (nbgl_button_t*)nbgl_objPoolGet(BUTTON,layer); - button->innerColor = WHITE; - button->borderColor = LIGHT_GRAY; - button->foregroundColor = BLACK; - button->obj.area.width = (SCREEN_WIDTH - (2*BORDER_MARGIN+2*INTERNAL_SMALL_MARGIN+BUTTON_DIAMETER))/2; - if (!withExitKey) - button->obj.area.width += BUTTON_DIAMETER/2; - button->obj.area.height = BUTTON_DIAMETER; - button->radius = BUTTON_RADIUS; - button->text = NULL; - button->icon = &C_rightArrow32px; - button->obj.alignmentMarginX = INTERNAL_SMALL_MARGIN; - button->obj.alignmentMarginY = 0; - button->obj.alignment = MID_RIGHT; - button->obj.alignTo = navContainer->children[PREVIOUS_PAGE_INDEX]; - button->obj.touchMask = (1<children[NEXT_PAGE_INDEX] = (nbgl_obj_t*)button; - - configButtons(navContainer, nbPages, activePage); - } - - return navContainer; + + return navContainer; } diff --git a/lib_nbgl/src/nbgl_obj.c b/lib_nbgl/src/nbgl_obj.c index b25218d74..e4f98371a 100644 --- a/lib_nbgl/src/nbgl_obj.c +++ b/lib_nbgl/src/nbgl_obj.c @@ -55,200 +55,252 @@ extern const char *get_ux_loc_string(uint32_t index); * GLOBAL FUNCTIONS **********************/ -static void compute_relativePosition(nbgl_obj_t* obj, nbgl_obj_t *prevObj) { - nbgl_container_t *parent = (nbgl_container_t*)(obj->parent); - // LOG_DEBUG(OBJ_LOGGER,"compute_relativePosition()\n"); - // compute object absolute position thanks to layout/alignment - if (obj->alignment == NO_ALIGNMENT) { - LOG_DEBUG(OBJ_LOGGER,"compute_relativePosition() without align to, parent->layout = %d, prevObj = %p\n",parent->layout,prevObj); - // align to parent, depending of layout - if (parent->layout == VERTICAL) { - obj->rel_x0 = obj->alignmentMarginX; - if (prevObj!=NULL) { - obj->rel_y0 = prevObj->rel_y0 + prevObj->area.height + obj->alignmentMarginY; - } - else { - obj->rel_y0 = obj->alignmentMarginY; - } - } - else { // HORIZONTAL - if (prevObj!=NULL) { - obj->rel_x0 = prevObj->rel_x0 + prevObj->area.width + obj->alignmentMarginX; - } - else { - obj->rel_x0 = obj->alignmentMarginX; - } - obj->rel_y0 = obj->alignmentMarginY; - } - } - else { - nbgl_obj_t *alignToObj = obj->alignTo; - if (alignToObj == NULL) { - alignToObj = obj->parent; - LOG_DEBUG(OBJ_LOGGER,"compute_relativePosition() with align to parent\n"); - } - else { - LOG_DEBUG(OBJ_LOGGER,"compute_relativePosition() with align to = %p\n",alignToObj); - } - // align to the given object, with the given constraints - if (alignToObj == obj->parent) { - // align inside if the reference is the parent - switch (obj->alignment) { - case TOP_LEFT: - obj->rel_x0 = obj->alignmentMarginX; - obj->rel_y0 = obj->alignmentMarginY; - break; - case TOP_MIDDLE: - obj->rel_x0 = (parent->obj.area.width - obj->area.width)/2 + obj->alignmentMarginX; - obj->rel_y0 = obj->alignmentMarginY; - break; - case TOP_RIGHT: - obj->rel_x0 = (parent->obj.area.width - obj->area.width) - obj->alignmentMarginX; - obj->rel_y0 = obj->alignmentMarginY; - break; - case MID_LEFT: - obj->rel_x0 = obj->alignmentMarginX; - obj->rel_y0 = (parent->obj.area.height - obj->area.height)/2 + obj->alignmentMarginY; - break; - case CENTER: - obj->rel_x0 = (parent->obj.area.width - obj->area.width)/2 + obj->alignmentMarginX; - obj->rel_y0 = (parent->obj.area.height - obj->area.height)/2 + obj->alignmentMarginY; - break; - case MID_RIGHT: - obj->rel_x0 = (parent->obj.area.width - obj->area.width) - obj->alignmentMarginX; - obj->rel_y0 = (parent->obj.area.height - obj->area.height)/2 + obj->alignmentMarginY; - break; - case BOTTOM_LEFT: - obj->rel_x0 = obj->alignmentMarginX; - obj->rel_y0 = (parent->obj.area.height - obj->area.height) - obj->alignmentMarginY; - break; - case BOTTOM_MIDDLE: - obj->rel_x0 = (parent->obj.area.width - obj->area.width)/2 + obj->alignmentMarginX; - obj->rel_y0 = (parent->obj.area.height - obj->area.height) - obj->alignmentMarginY; - break; - case BOTTOM_RIGHT: - obj->rel_x0 = (parent->obj.area.width - obj->area.width) - obj->alignmentMarginX; - obj->rel_y0 = (parent->obj.area.height - obj->area.height) - obj->alignmentMarginY; - break; - default: - //not supported - break; - } +static void compute_relativePosition(nbgl_obj_t *obj, nbgl_obj_t *prevObj) +{ + nbgl_container_t *parent = (nbgl_container_t *) (obj->parent); + // LOG_DEBUG(OBJ_LOGGER,"compute_relativePosition()\n"); + // compute object absolute position thanks to layout/alignment + if (obj->alignment == NO_ALIGNMENT) { + LOG_DEBUG( + OBJ_LOGGER, + "compute_relativePosition() without align to, parent->layout = %d, prevObj = %p\n", + parent->layout, + prevObj); + // align to parent, depending of layout + if (parent->layout == VERTICAL) { + obj->rel_x0 = obj->alignmentMarginX; + if (prevObj != NULL) { + obj->rel_y0 = prevObj->rel_y0 + prevObj->area.height + obj->alignmentMarginY; + } + else { + obj->rel_y0 = obj->alignmentMarginY; + } + } + else { // HORIZONTAL + if (prevObj != NULL) { + obj->rel_x0 = prevObj->rel_x0 + prevObj->area.width + obj->alignmentMarginX; + } + else { + obj->rel_x0 = obj->alignmentMarginX; + } + obj->rel_y0 = obj->alignmentMarginY; + } } else { - // align outside if the reference is a "brother" - switch (obj->alignment) { - case TOP_LEFT: - obj->rel_x0 = alignToObj->rel_x0 + obj->alignmentMarginX; - obj->rel_y0 = alignToObj->rel_y0 - obj->area.height - obj->alignmentMarginY; - break; - case TOP_MIDDLE: - obj->rel_x0 = alignToObj->rel_x0 + (alignToObj->area.width - obj->area.width)/2 + obj->alignmentMarginX; - obj->rel_y0 = alignToObj->rel_y0 - obj->area.height - obj->alignmentMarginY; - break; - case TOP_RIGHT: - obj->rel_x0 = alignToObj->rel_x0 + (alignToObj->area.width - obj->area.width) - obj->alignmentMarginX; - obj->rel_y0 = alignToObj->rel_y0 - obj->area.height - obj->alignmentMarginY; - break; - - case LEFT_TOP: - obj->rel_x0 = alignToObj->rel_x0 - obj->area.width - obj->alignmentMarginX; - obj->rel_y0 = alignToObj->rel_y0 + obj->alignmentMarginY; - break; - case MID_LEFT: - obj->rel_x0 = alignToObj->rel_x0 - obj->area.width - obj->alignmentMarginX; - obj->rel_y0 = alignToObj->rel_y0 + (alignToObj->area.height - obj->area.height)/2 + obj->alignmentMarginY; - break; - case LEFT_BOTTOM: - obj->rel_x0 = alignToObj->rel_x0 - obj->area.width - obj->alignmentMarginX; - obj->rel_y0 = alignToObj->rel_y0 + (alignToObj->area.height - obj->area.height) + obj->alignmentMarginY; - break; - - case RIGHT_TOP: - obj->rel_x0 = alignToObj->rel_x0 + alignToObj->area.width + obj->alignmentMarginX; - obj->rel_y0 = alignToObj->rel_y0 + obj->alignmentMarginY; - break; - case MID_RIGHT: - obj->rel_x0 = alignToObj->rel_x0 + alignToObj->area.width + obj->alignmentMarginX; - obj->rel_y0 = alignToObj->rel_y0 + (alignToObj->area.height - obj->area.height)/2 + obj->alignmentMarginY; - break; - case RIGHT_BOTTOM: - obj->rel_x0 = alignToObj->rel_x0 + alignToObj->area.width + obj->alignmentMarginX; - obj->rel_y0 = alignToObj->rel_y0 + (alignToObj->area.height - obj->area.height) + obj->alignmentMarginY; - break; - - case BOTTOM_LEFT: - obj->rel_x0 = alignToObj->rel_x0 + obj->alignmentMarginX; - obj->rel_y0 = alignToObj->rel_y0 + alignToObj->area.height + obj->alignmentMarginY; - break; - case BOTTOM_MIDDLE: - obj->rel_x0 = alignToObj->rel_x0 + (alignToObj->area.width - obj->area.width)/2 + obj->alignmentMarginX; - obj->rel_y0 = alignToObj->rel_y0 + alignToObj->area.height + obj->alignmentMarginY; - break; - case BOTTOM_RIGHT: - obj->rel_x0 = alignToObj->rel_x0 + (alignToObj->area.width - obj->area.width) - obj->alignmentMarginX; - obj->rel_y0 = alignToObj->rel_y0 + alignToObj->area.height + obj->alignmentMarginY; - break; - default: - //not supported - break; - } + nbgl_obj_t *alignToObj = obj->alignTo; + if (alignToObj == NULL) { + alignToObj = obj->parent; + LOG_DEBUG(OBJ_LOGGER, "compute_relativePosition() with align to parent\n"); + } + else { + LOG_DEBUG(OBJ_LOGGER, "compute_relativePosition() with align to = %p\n", alignToObj); + } + // align to the given object, with the given constraints + if (alignToObj == obj->parent) { + // align inside if the reference is the parent + switch (obj->alignment) { + case TOP_LEFT: + obj->rel_x0 = obj->alignmentMarginX; + obj->rel_y0 = obj->alignmentMarginY; + break; + case TOP_MIDDLE: + obj->rel_x0 + = (parent->obj.area.width - obj->area.width) / 2 + obj->alignmentMarginX; + obj->rel_y0 = obj->alignmentMarginY; + break; + case TOP_RIGHT: + obj->rel_x0 + = (parent->obj.area.width - obj->area.width) - obj->alignmentMarginX; + obj->rel_y0 = obj->alignmentMarginY; + break; + case MID_LEFT: + obj->rel_x0 = obj->alignmentMarginX; + obj->rel_y0 + = (parent->obj.area.height - obj->area.height) / 2 + obj->alignmentMarginY; + break; + case CENTER: + obj->rel_x0 + = (parent->obj.area.width - obj->area.width) / 2 + obj->alignmentMarginX; + obj->rel_y0 + = (parent->obj.area.height - obj->area.height) / 2 + obj->alignmentMarginY; + break; + case MID_RIGHT: + obj->rel_x0 + = (parent->obj.area.width - obj->area.width) - obj->alignmentMarginX; + obj->rel_y0 + = (parent->obj.area.height - obj->area.height) / 2 + obj->alignmentMarginY; + break; + case BOTTOM_LEFT: + obj->rel_x0 = obj->alignmentMarginX; + obj->rel_y0 + = (parent->obj.area.height - obj->area.height) - obj->alignmentMarginY; + break; + case BOTTOM_MIDDLE: + obj->rel_x0 + = (parent->obj.area.width - obj->area.width) / 2 + obj->alignmentMarginX; + obj->rel_y0 + = (parent->obj.area.height - obj->area.height) - obj->alignmentMarginY; + break; + case BOTTOM_RIGHT: + obj->rel_x0 + = (parent->obj.area.width - obj->area.width) - obj->alignmentMarginX; + obj->rel_y0 + = (parent->obj.area.height - obj->area.height) - obj->alignmentMarginY; + break; + default: + // not supported + break; + } + } + else { + // align outside if the reference is a "brother" + switch (obj->alignment) { + case TOP_LEFT: + obj->rel_x0 = alignToObj->rel_x0 + obj->alignmentMarginX; + obj->rel_y0 = alignToObj->rel_y0 - obj->area.height - obj->alignmentMarginY; + break; + case TOP_MIDDLE: + obj->rel_x0 = alignToObj->rel_x0 + + (alignToObj->area.width - obj->area.width) / 2 + + obj->alignmentMarginX; + obj->rel_y0 = alignToObj->rel_y0 - obj->area.height - obj->alignmentMarginY; + break; + case TOP_RIGHT: + obj->rel_x0 = alignToObj->rel_x0 + (alignToObj->area.width - obj->area.width) + - obj->alignmentMarginX; + obj->rel_y0 = alignToObj->rel_y0 - obj->area.height - obj->alignmentMarginY; + break; + + case LEFT_TOP: + obj->rel_x0 = alignToObj->rel_x0 - obj->area.width - obj->alignmentMarginX; + obj->rel_y0 = alignToObj->rel_y0 + obj->alignmentMarginY; + break; + case MID_LEFT: + obj->rel_x0 = alignToObj->rel_x0 - obj->area.width - obj->alignmentMarginX; + obj->rel_y0 = alignToObj->rel_y0 + + (alignToObj->area.height - obj->area.height) / 2 + + obj->alignmentMarginY; + break; + case LEFT_BOTTOM: + obj->rel_x0 = alignToObj->rel_x0 - obj->area.width - obj->alignmentMarginX; + obj->rel_y0 = alignToObj->rel_y0 + (alignToObj->area.height - obj->area.height) + + obj->alignmentMarginY; + break; + + case RIGHT_TOP: + obj->rel_x0 + = alignToObj->rel_x0 + alignToObj->area.width + obj->alignmentMarginX; + obj->rel_y0 = alignToObj->rel_y0 + obj->alignmentMarginY; + break; + case MID_RIGHT: + obj->rel_x0 + = alignToObj->rel_x0 + alignToObj->area.width + obj->alignmentMarginX; + obj->rel_y0 = alignToObj->rel_y0 + + (alignToObj->area.height - obj->area.height) / 2 + + obj->alignmentMarginY; + break; + case RIGHT_BOTTOM: + obj->rel_x0 + = alignToObj->rel_x0 + alignToObj->area.width + obj->alignmentMarginX; + obj->rel_y0 = alignToObj->rel_y0 + (alignToObj->area.height - obj->area.height) + + obj->alignmentMarginY; + break; + + case BOTTOM_LEFT: + obj->rel_x0 = alignToObj->rel_x0 + obj->alignmentMarginX; + obj->rel_y0 + = alignToObj->rel_y0 + alignToObj->area.height + obj->alignmentMarginY; + break; + case BOTTOM_MIDDLE: + obj->rel_x0 = alignToObj->rel_x0 + + (alignToObj->area.width - obj->area.width) / 2 + + obj->alignmentMarginX; + obj->rel_y0 + = alignToObj->rel_y0 + alignToObj->area.height + obj->alignmentMarginY; + break; + case BOTTOM_RIGHT: + obj->rel_x0 = alignToObj->rel_x0 + (alignToObj->area.width - obj->area.width) + - obj->alignmentMarginX; + obj->rel_y0 + = alignToObj->rel_y0 + alignToObj->area.height + obj->alignmentMarginY; + break; + default: + // not supported + break; + } + } } - } - // align on multiples of 4 - obj->rel_y0 &= ~0x3; + // align on multiples of 4 + obj->rel_y0 &= ~0x3; } -static void compute_position(nbgl_obj_t* obj, nbgl_obj_t *prevObj) { - nbgl_container_t *parent = (nbgl_container_t*)(obj->parent); - - compute_relativePosition(obj,prevObj); - - if (parent == NULL) { - // HUGE issue - return; - } - //LOG_DEBUG(OBJ_LOGGER,"compute_position(), parent.type = %d, parent->obj.area.x0 = %d, obj->rel_x0=%d\n",parent->type,parent->obj.area.x0,obj->rel_x0); - //LOG_DEBUG(OBJ_LOGGER,"compute_position(), parent->obj.area.y0 = %d, obj->rel_y0=%d\n",parent->obj.area.y0,obj->rel_y0); +static void compute_position(nbgl_obj_t *obj, nbgl_obj_t *prevObj) +{ + nbgl_container_t *parent = (nbgl_container_t *) (obj->parent); - obj->area.x0 = parent->obj.area.x0+obj->rel_x0; - obj->area.y0 = parent->obj.area.y0+obj->rel_y0; + compute_relativePosition(obj, prevObj); - if ((obj->area.x0+obj->area.width)>SCREEN_WIDTH) { - LOG_FATAL(OBJ_LOGGER,"compute_position(), forbidden width, obj->type = %d, x0=%d, width=%d\n",obj->type,obj->area.x0,obj->area.width); - } - if ((obj->area.y0+obj->area.height)>SCREEN_HEIGHT) { - LOG_FATAL(OBJ_LOGGER,"compute_position(), forbidden height, obj->type = %d, y0=%d, height=%d\n",obj->type,obj->area.y0,obj->area.height); - } + if (parent == NULL) { + // HUGE issue + return; + } + // LOG_DEBUG(OBJ_LOGGER,"compute_position(), parent.type = %d, parent->obj.area.x0 = %d, + // obj->rel_x0=%d\n",parent->type,parent->obj.area.x0,obj->rel_x0); + // LOG_DEBUG(OBJ_LOGGER,"compute_position(), parent->obj.area.y0 = %d, + // obj->rel_y0=%d\n",parent->obj.area.y0,obj->rel_y0); + + obj->area.x0 = parent->obj.area.x0 + obj->rel_x0; + obj->area.y0 = parent->obj.area.y0 + obj->rel_y0; + + if ((obj->area.x0 + obj->area.width) > SCREEN_WIDTH) { + LOG_FATAL(OBJ_LOGGER, + "compute_position(), forbidden width, obj->type = %d, x0=%d, width=%d\n", + obj->type, + obj->area.x0, + obj->area.width); + } + if ((obj->area.y0 + obj->area.height) > SCREEN_HEIGHT) { + LOG_FATAL(OBJ_LOGGER, + "compute_position(), forbidden height, obj->type = %d, y0=%d, height=%d\n", + obj->type, + obj->area.y0, + obj->area.height); + } } -static void draw_screen(nbgl_container_t *obj) { - nbgl_area_t rectArea; - - if (objDrawingDisabled) { - return; - } - rectArea.backgroundColor = obj->obj.area.backgroundColor; - rectArea.x0 = obj->obj.area.x0; - rectArea.y0 = obj->obj.area.y0; - rectArea.width = obj->obj.area.width; - rectArea.height = obj->obj.area.height; - nbgl_frontDrawRect(&rectArea); +static void draw_screen(nbgl_container_t *obj) +{ + nbgl_area_t rectArea; + + if (objDrawingDisabled) { + return; + } + rectArea.backgroundColor = obj->obj.area.backgroundColor; + rectArea.x0 = obj->obj.area.x0; + rectArea.y0 = obj->obj.area.y0; + rectArea.width = obj->obj.area.width; + rectArea.height = obj->obj.area.height; + nbgl_frontDrawRect(&rectArea); } -static void draw_container(nbgl_container_t* obj, nbgl_obj_t *prevObj, bool computePosition) { - if (computePosition) { - compute_position((nbgl_obj_t *)obj,prevObj); - } - if (objDrawingDisabled) { - return; - } - LOG_DEBUG(OBJ_LOGGER,"draw_container(), x0 = %d, y0 = %d, width = %d\n", obj->obj.area.x0, obj->obj.area.y0, obj->obj.area.width); - // inherit background from parent - obj->obj.area.backgroundColor = obj->obj.parent->area.backgroundColor; - if (obj->forceClean) { - nbgl_frontDrawRect((nbgl_area_t*)obj); - } +static void draw_container(nbgl_container_t *obj, nbgl_obj_t *prevObj, bool computePosition) +{ + if (computePosition) { + compute_position((nbgl_obj_t *) obj, prevObj); + } + if (objDrawingDisabled) { + return; + } + LOG_DEBUG(OBJ_LOGGER, + "draw_container(), x0 = %d, y0 = %d, width = %d\n", + obj->obj.area.x0, + obj->obj.area.y0, + obj->obj.area.width); + // inherit background from parent + obj->obj.area.backgroundColor = obj->obj.parent->area.backgroundColor; + if (obj->forceClean) { + nbgl_frontDrawRect((nbgl_area_t *) obj); + } } /** @@ -259,241 +311,263 @@ static void draw_container(nbgl_container_t* obj, nbgl_obj_t *prevObj, bool comp * @param prevObj the previous object drawned in the same container, with the default layout * @param computePosition if true, force to compute the object position */ -static void draw_button(nbgl_button_t* obj, nbgl_obj_t *prevObj, bool computePosition) { - uint16_t textWidth = 0; - const char *text = NULL; - - if (computePosition) { - compute_position((nbgl_obj_t *)obj,prevObj); - } - if (objDrawingDisabled) { - return; - } - LOG_DEBUG(OBJ_LOGGER,"draw_button(), x0 = %d, y0 = %d, width = %d, height = %d\n", obj->obj.area.x0, obj->obj.area.y0, obj->obj.area.width, obj->obj.area.height); - - // inherit background from parent - obj->obj.area.backgroundColor = obj->obj.parent->area.backgroundColor; - // draw the rounded corner rectangle - if (obj->innerColor == obj->borderColor) { - nbgl_drawRoundedRect((nbgl_area_t*)obj, - obj->radius, - obj->innerColor); - } - else { - nbgl_drawRoundedBorderedRect((nbgl_area_t*)obj, - obj->radius, 2, - obj->innerColor, obj->borderColor); - } - // get the text of the button from the callback if not NULL - if (obj->onDrawCallback != NULL) { - obj->text = obj->onDrawCallback(obj->token); - } - else { - if (obj->localized == true) { -#if defined(HAVE_LANGUAGE_PACK) - obj->text = get_ux_loc_string(obj->textId); -#endif // HAVE_LANGUAGE_PACK +static void draw_button(nbgl_button_t *obj, nbgl_obj_t *prevObj, bool computePosition) +{ + uint16_t textWidth = 0; + const char *text = NULL; + + if (computePosition) { + compute_position((nbgl_obj_t *) obj, prevObj); } - } - text = obj->text; - // draw the text (right of the icon, with 8 pixels between them) - if (text != NULL) { - nbgl_area_t rectArea; - textWidth = nbgl_getTextWidth(obj->fontId, text); - if (obj->icon != NULL) { - rectArea.x0 = obj->obj.area.x0 + obj->obj.area.width/2 - (textWidth+obj->icon->width+8)/2 + obj->icon->width + 8; + if (objDrawingDisabled) { + return; } - else { - rectArea.x0 = obj->obj.area.x0 + (obj->obj.area.width - textWidth)/2; - } - LOG_DEBUG(OBJ_LOGGER,"draw_button(), text = %s\n", text); - rectArea.y0 = obj->obj.area.y0 + (obj->obj.area.height - nbgl_getFontHeight(obj->fontId))/2; - rectArea.width = textWidth; - rectArea.height = nbgl_getFontHeight(obj->fontId); - rectArea.backgroundColor = obj->innerColor; - nbgl_drawText(&rectArea, text, nbgl_getTextLength(text), obj->fontId, obj->foregroundColor); - } - // draw the icon, if any - if (obj->icon != NULL) { - uint16_t iconX0, iconY0; - nbgl_area_t rectArea; + LOG_DEBUG(OBJ_LOGGER, + "draw_button(), x0 = %d, y0 = %d, width = %d, height = %d\n", + obj->obj.area.x0, + obj->obj.area.y0, + obj->obj.area.width, + obj->obj.area.height); - if (text != NULL) { - iconX0 = obj->obj.area.x0 + (obj->obj.area.width - (textWidth+obj->icon->width+8))/2; + // inherit background from parent + obj->obj.area.backgroundColor = obj->obj.parent->area.backgroundColor; + // draw the rounded corner rectangle + if (obj->innerColor == obj->borderColor) { + nbgl_drawRoundedRect((nbgl_area_t *) obj, obj->radius, obj->innerColor); } else { - iconX0 = obj->obj.area.x0 + (obj->obj.area.width- obj->icon->width)/2; + nbgl_drawRoundedBorderedRect( + (nbgl_area_t *) obj, obj->radius, 2, obj->innerColor, obj->borderColor); } - LOG_DEBUG(OBJ_LOGGER,"draw_button(), obj->obj.area.height = %d, obj->iconHeight = %d\n", obj->obj.area.height , obj->icon->height); - iconY0 = obj->obj.area.y0 + (obj->obj.area.height - obj->icon->height)/2; - - rectArea.backgroundColor = obj->innerColor; - rectArea.x0 = iconX0; - rectArea.y0 = iconY0; - rectArea.width = obj->icon->width; - rectArea.height = obj->icon->height; - rectArea.bpp = obj->icon->bpp; + // get the text of the button from the callback if not NULL + if (obj->onDrawCallback != NULL) { + obj->text = obj->onDrawCallback(obj->token); + } + else { + if (obj->localized == true) { +#if defined(HAVE_LANGUAGE_PACK) + obj->text = get_ux_loc_string(obj->textId); +#endif // HAVE_LANGUAGE_PACK + } + } + text = obj->text; + // draw the text (right of the icon, with 8 pixels between them) + if (text != NULL) { + nbgl_area_t rectArea; + textWidth = nbgl_getTextWidth(obj->fontId, text); + if (obj->icon != NULL) { + rectArea.x0 = obj->obj.area.x0 + obj->obj.area.width / 2 + - (textWidth + obj->icon->width + 8) / 2 + obj->icon->width + 8; + } + else { + rectArea.x0 = obj->obj.area.x0 + (obj->obj.area.width - textWidth) / 2; + } + LOG_DEBUG(OBJ_LOGGER, "draw_button(), text = %s\n", text); + rectArea.y0 + = obj->obj.area.y0 + (obj->obj.area.height - nbgl_getFontHeight(obj->fontId)) / 2; + rectArea.width = textWidth; + rectArea.height = nbgl_getFontHeight(obj->fontId); + rectArea.backgroundColor = obj->innerColor; + nbgl_drawText(&rectArea, text, nbgl_getTextLength(text), obj->fontId, obj->foregroundColor); + } + // draw the icon, if any + if (obj->icon != NULL) { + uint16_t iconX0, iconY0; + nbgl_area_t rectArea; - nbgl_drawIcon(&rectArea, obj->foregroundColor, obj->icon); - } + if (text != NULL) { + iconX0 + = obj->obj.area.x0 + (obj->obj.area.width - (textWidth + obj->icon->width + 8)) / 2; + } + else { + iconX0 = obj->obj.area.x0 + (obj->obj.area.width - obj->icon->width) / 2; + } + LOG_DEBUG(OBJ_LOGGER, + "draw_button(), obj->obj.area.height = %d, obj->iconHeight = %d\n", + obj->obj.area.height, + obj->icon->height); + iconY0 = obj->obj.area.y0 + (obj->obj.area.height - obj->icon->height) / 2; + + rectArea.backgroundColor = obj->innerColor; + rectArea.x0 = iconX0; + rectArea.y0 = iconY0; + rectArea.width = obj->icon->width; + rectArea.height = obj->icon->height; + rectArea.bpp = obj->icon->bpp; + + nbgl_drawIcon(&rectArea, obj->foregroundColor, obj->icon); + } } /** - * @brief internal function used to draw a vertical or horizontal line, up to 4 pixels thick (@ref LINE type) + * @brief internal function used to draw a vertical or horizontal line, up to 4 pixels thick (@ref + * LINE type) * * @param obj the object to draw * @param prevObj the previous object drawned in the same container, with the default layout * @param computePosition if true, force to compute the object position */ -static void draw_line(nbgl_line_t* obj, nbgl_obj_t *prevObj, bool computePosition) { - nbgl_area_t rectArea; - if (computePosition) { - compute_position((nbgl_obj_t *)obj,prevObj); - } - if (objDrawingDisabled) { - return; - } - LOG_DEBUG(OBJ_LOGGER,"draw_line(), x0 = %d, y0 = %d\n", obj->obj.area.x0, obj->obj.area.y0); - // inherit background from parent - obj->obj.area.backgroundColor = obj->obj.parent->area.backgroundColor; - LOG_DEBUG(OBJ_LOGGER,"draw_line(), backgroundColor = %d, lineColor = %d\n", obj->obj.area.backgroundColor,obj->lineColor); - rectArea.x0 = obj->obj.area.x0; - rectArea.y0 = obj->obj.area.y0; - if (obj->direction == VERTICAL) { - rectArea.width = obj->obj.area.width = obj->thickness; - rectArea.backgroundColor = obj->lineColor; - rectArea.height = obj->obj.area.height; - nbgl_frontDrawRect(&rectArea); - } - else { - uint8_t mask; - if (obj->thickness == 1) { - mask = 0x1 << (obj->offset&0x3); - } - else if (obj->thickness == 2) { - mask = 0x3 << ((obj->offset<3)?obj->offset:2); +static void draw_line(nbgl_line_t *obj, nbgl_obj_t *prevObj, bool computePosition) +{ + nbgl_area_t rectArea; + if (computePosition) { + compute_position((nbgl_obj_t *) obj, prevObj); } - else if (obj->thickness == 3) { - mask = 0x7 << (obj->offset&0x1); + if (objDrawingDisabled) { + return; } - else if (obj->thickness == 4) { - mask = 0xF; + LOG_DEBUG(OBJ_LOGGER, "draw_line(), x0 = %d, y0 = %d\n", obj->obj.area.x0, obj->obj.area.y0); + // inherit background from parent + obj->obj.area.backgroundColor = obj->obj.parent->area.backgroundColor; + LOG_DEBUG(OBJ_LOGGER, + "draw_line(), backgroundColor = %d, lineColor = %d\n", + obj->obj.area.backgroundColor, + obj->lineColor); + rectArea.x0 = obj->obj.area.x0; + rectArea.y0 = obj->obj.area.y0; + if (obj->direction == VERTICAL) { + rectArea.width = obj->obj.area.width = obj->thickness; + rectArea.backgroundColor = obj->lineColor; + rectArea.height = obj->obj.area.height; + nbgl_frontDrawRect(&rectArea); } else { - LOG_WARN(OBJ_LOGGER,"draw_line(), forbidden thickness = %d\n", obj->thickness); - return; + uint8_t mask; + if (obj->thickness == 1) { + mask = 0x1 << (obj->offset & 0x3); + } + else if (obj->thickness == 2) { + mask = 0x3 << ((obj->offset < 3) ? obj->offset : 2); + } + else if (obj->thickness == 3) { + mask = 0x7 << (obj->offset & 0x1); + } + else if (obj->thickness == 4) { + mask = 0xF; + } + else { + LOG_WARN(OBJ_LOGGER, "draw_line(), forbidden thickness = %d\n", obj->thickness); + return; + } + rectArea.width = obj->obj.area.width; + rectArea.height = obj->obj.area.height = 4; + rectArea.backgroundColor = obj->obj.area.backgroundColor; + nbgl_frontDrawHorizontalLine(&rectArea, mask, obj->lineColor); } - rectArea.width = obj->obj.area.width; - rectArea.height = obj->obj.area.height = 4; - rectArea.backgroundColor = obj->obj.area.backgroundColor; - nbgl_frontDrawHorizontalLine(&rectArea,mask,obj->lineColor); - } } -static void draw_image(nbgl_image_t* obj, nbgl_obj_t *prevObj, bool computePosition) { - const nbgl_icon_details_t *iconDetails; - nbgl_color_map_t colorMap; +static void draw_image(nbgl_image_t *obj, nbgl_obj_t *prevObj, bool computePosition) +{ + const nbgl_icon_details_t *iconDetails; + nbgl_color_map_t colorMap; - // if buffer is NULL, let's try to call onDrawCallback, if not NULL, to get it - if (obj->buffer == NULL) { - if (obj->onDrawCallback != NULL) { - iconDetails = obj->onDrawCallback(obj->token); + // if buffer is NULL, let's try to call onDrawCallback, if not NULL, to get it + if (obj->buffer == NULL) { + if (obj->onDrawCallback != NULL) { + iconDetails = obj->onDrawCallback(obj->token); + } + else { + return; + } + } + else { + iconDetails = obj->buffer; + } + + // use dimension and bpp from the icon details + obj->obj.area.width = iconDetails->width; + obj->obj.area.height = iconDetails->height; + obj->obj.area.bpp = iconDetails->bpp; + if (computePosition) { + compute_position((nbgl_obj_t *) obj, prevObj); + } + if (objDrawingDisabled) { + return; + } + LOG_DEBUG(OBJ_LOGGER, "draw_image(), x0 = %d, y0 = %d\n", obj->obj.area.x0, obj->obj.area.y0); + // inherit background from parent + obj->obj.area.backgroundColor = obj->obj.parent->area.backgroundColor; + if (obj->obj.area.bpp == NBGL_BPP_1) { + colorMap = obj->foregroundColor; + } + else if (obj->obj.area.bpp == NBGL_BPP_2) { + colorMap = ((WHITE << 6) | (LIGHT_GRAY << 4) | (DARK_GRAY << 2) | BLACK); } else { - return; - } - } - else { - iconDetails = obj->buffer; - } - - // use dimension and bpp from the icon details - obj->obj.area.width = iconDetails->width; - obj->obj.area.height = iconDetails->height; - obj->obj.area.bpp = iconDetails->bpp; - if (computePosition) { - compute_position((nbgl_obj_t *)obj,prevObj); - } - if (objDrawingDisabled) { - return; - } - LOG_DEBUG(OBJ_LOGGER,"draw_image(), x0 = %d, y0 = %d\n", obj->obj.area.x0, obj->obj.area.y0); - // inherit background from parent - obj->obj.area.backgroundColor = obj->obj.parent->area.backgroundColor; - if (obj->obj.area.bpp == NBGL_BPP_1) { - colorMap = obj->foregroundColor; - } - else if (obj->obj.area.bpp == NBGL_BPP_2) { - colorMap = ((WHITE<<6)|(LIGHT_GRAY<<4)|(DARK_GRAY<<2)|BLACK); - } - else { - colorMap = obj->foregroundColor; - } - - nbgl_drawIcon((nbgl_area_t *) obj, colorMap, iconDetails); + colorMap = obj->foregroundColor; + } + + nbgl_drawIcon((nbgl_area_t *) obj, colorMap, iconDetails); } -static void draw_switch(nbgl_switch_t* obj, nbgl_obj_t *prevObj, bool computePosition) { - nbgl_area_t rectArea; - - // force dimensions - obj->obj.area.width = C_switch_60_40.width; - obj->obj.area.height = C_switch_60_40.height; - if (computePosition) { - compute_position((nbgl_obj_t *)obj,prevObj); - } - if (objDrawingDisabled) { - return; - } - LOG_DEBUG(OBJ_LOGGER,"draw_switch(), x0 = %d, y0 = %d\n", obj->obj.area.x0, obj->obj.area.y0); - - // inherit background from parent - obj->obj.area.backgroundColor = obj->obj.parent->area.backgroundColor; - - rectArea.x0 = obj->obj.area.x0; - rectArea.y0 = obj->obj.area.y0; - rectArea.width = obj->obj.area.width; - rectArea.height = obj->obj.area.height; - rectArea.backgroundColor = obj->obj.area.backgroundColor; - rectArea.bpp = NBGL_BPP_1; - if (obj->state == OFF_STATE) { - nbgl_frontDrawImage(&rectArea,(uint8_t*)C_switch_60_40.bitmap,NO_TRANSFORMATION,obj->offColor); - } - else { - nbgl_frontDrawImage(&rectArea, - (uint8_t*)C_switch_60_40.bitmap,VERTICAL_MIRROR,obj->onColor); - } +static void draw_switch(nbgl_switch_t *obj, nbgl_obj_t *prevObj, bool computePosition) +{ + nbgl_area_t rectArea; + + // force dimensions + obj->obj.area.width = C_switch_60_40.width; + obj->obj.area.height = C_switch_60_40.height; + if (computePosition) { + compute_position((nbgl_obj_t *) obj, prevObj); + } + if (objDrawingDisabled) { + return; + } + LOG_DEBUG(OBJ_LOGGER, "draw_switch(), x0 = %d, y0 = %d\n", obj->obj.area.x0, obj->obj.area.y0); + + // inherit background from parent + obj->obj.area.backgroundColor = obj->obj.parent->area.backgroundColor; + + rectArea.x0 = obj->obj.area.x0; + rectArea.y0 = obj->obj.area.y0; + rectArea.width = obj->obj.area.width; + rectArea.height = obj->obj.area.height; + rectArea.backgroundColor = obj->obj.area.backgroundColor; + rectArea.bpp = NBGL_BPP_1; + if (obj->state == OFF_STATE) { + nbgl_frontDrawImage( + &rectArea, (uint8_t *) C_switch_60_40.bitmap, NO_TRANSFORMATION, obj->offColor); + } + else { + nbgl_frontDrawImage( + &rectArea, (uint8_t *) C_switch_60_40.bitmap, VERTICAL_MIRROR, obj->onColor); + } } -static void draw_radioButton(nbgl_radio_t* obj, nbgl_obj_t *prevObj, bool computePosition) { - nbgl_area_t rectArea; - - // force dimensions - obj->obj.area.width = 32; - obj->obj.area.height = 32; - if (computePosition) { - compute_position((nbgl_obj_t *)obj,prevObj); - } - if (objDrawingDisabled) { - return; - } - LOG_DEBUG(OBJ_LOGGER,"draw_radioButton(), x0 = %d, y0 = %d, state = %d\n", obj->obj.area.x0, obj->obj.area.y0, obj->state); - - // inherit background from parent - obj->obj.area.backgroundColor = obj->obj.parent->area.backgroundColor; - - rectArea.x0 = obj->obj.area.x0; - rectArea.y0 = obj->obj.area.y0; - rectArea.width = obj->obj.area.width; - rectArea.height = obj->obj.area.height; - rectArea.backgroundColor = obj->obj.area.backgroundColor; - rectArea.bpp = NBGL_BPP_1; - if (obj->state == OFF_STATE) { - nbgl_drawIcon(&rectArea, obj->borderColor, &C_radio_inactive_32px); - } - else { - nbgl_drawIcon(&rectArea, obj->activeColor, &C_radio_active_32px); - } +static void draw_radioButton(nbgl_radio_t *obj, nbgl_obj_t *prevObj, bool computePosition) +{ + nbgl_area_t rectArea; + + // force dimensions + obj->obj.area.width = 32; + obj->obj.area.height = 32; + if (computePosition) { + compute_position((nbgl_obj_t *) obj, prevObj); + } + if (objDrawingDisabled) { + return; + } + LOG_DEBUG(OBJ_LOGGER, + "draw_radioButton(), x0 = %d, y0 = %d, state = %d\n", + obj->obj.area.x0, + obj->obj.area.y0, + obj->state); + + // inherit background from parent + obj->obj.area.backgroundColor = obj->obj.parent->area.backgroundColor; + + rectArea.x0 = obj->obj.area.x0; + rectArea.y0 = obj->obj.area.y0; + rectArea.width = obj->obj.area.width; + rectArea.height = obj->obj.area.height; + rectArea.backgroundColor = obj->obj.area.backgroundColor; + rectArea.bpp = NBGL_BPP_1; + if (obj->state == OFF_STATE) { + nbgl_drawIcon(&rectArea, obj->borderColor, &C_radio_inactive_32px); + } + else { + nbgl_drawIcon(&rectArea, obj->activeColor, &C_radio_active_32px); + } } /** @@ -503,38 +577,45 @@ static void draw_radioButton(nbgl_radio_t* obj, nbgl_obj_t *prevObj, bool comput * @param prevObj the previous object drawned in the same container, with the default layout * @param computePosition if TRUE, force to compute the object position */ -static void draw_progressBar(nbgl_progress_bar_t* obj, nbgl_obj_t *prevObj, bool computePosition) { - uint8_t stroke = 3; // 3 pixels for border - uint16_t levelWidth; - - if (computePosition) { - compute_position((nbgl_obj_t *)obj,prevObj); - } - if (objDrawingDisabled) { - return; - } - LOG_DEBUG(OBJ_LOGGER,"draw_progressBar(), x0 = %d, y0 = %d, level = %d %%\n", obj->obj.area.x0, obj->obj.area.y0, obj->state); - - // inherit background from parent - obj->obj.area.backgroundColor = obj->obj.parent->area.backgroundColor; - - // draw external part if necessary - if (obj->withBorder) { - nbgl_drawRoundedBorderedRect((nbgl_area_t*)obj, - RADIUS_0_PIXELS, stroke, obj->obj.area.backgroundColor, obj->foregroundColor); - } else { - nbgl_drawRoundedRect((nbgl_area_t*)obj, - RADIUS_0_PIXELS, obj->obj.area.backgroundColor); - } - // draw level - levelWidth = MIN(obj->obj.area.width * obj->state / 100, obj->obj.area.width); - if (levelWidth > 0) { - uint16_t tmp_width = obj->obj.area.width; - obj->obj.area.width = levelWidth; - nbgl_drawRoundedRect((nbgl_area_t*)obj, - RADIUS_0_PIXELS, obj->foregroundColor); - obj->obj.area.width = tmp_width; - } +static void draw_progressBar(nbgl_progress_bar_t *obj, nbgl_obj_t *prevObj, bool computePosition) +{ + uint8_t stroke = 3; // 3 pixels for border + uint16_t levelWidth; + + if (computePosition) { + compute_position((nbgl_obj_t *) obj, prevObj); + } + if (objDrawingDisabled) { + return; + } + LOG_DEBUG(OBJ_LOGGER, + "draw_progressBar(), x0 = %d, y0 = %d, level = %d %%\n", + obj->obj.area.x0, + obj->obj.area.y0, + obj->state); + + // inherit background from parent + obj->obj.area.backgroundColor = obj->obj.parent->area.backgroundColor; + + // draw external part if necessary + if (obj->withBorder) { + nbgl_drawRoundedBorderedRect((nbgl_area_t *) obj, + RADIUS_0_PIXELS, + stroke, + obj->obj.area.backgroundColor, + obj->foregroundColor); + } + else { + nbgl_drawRoundedRect((nbgl_area_t *) obj, RADIUS_0_PIXELS, obj->obj.area.backgroundColor); + } + // draw level + levelWidth = MIN(obj->obj.area.width * obj->state / 100, obj->obj.area.width); + if (levelWidth > 0) { + uint16_t tmp_width = obj->obj.area.width; + obj->obj.area.width = levelWidth; + nbgl_drawRoundedRect((nbgl_area_t *) obj, RADIUS_0_PIXELS, obj->foregroundColor); + obj->obj.area.width = tmp_width; + } } /** @@ -545,73 +626,86 @@ static void draw_progressBar(nbgl_progress_bar_t* obj, nbgl_obj_t *prevObj, bool * @param prevObj the previous object drawned in the same container, with the default layout * @param computePosition if TRUE, force to compute the object position */ -static void draw_pageIndicator(nbgl_page_indicator_t* obj, nbgl_obj_t *prevObj, bool computePosition) { - nbgl_area_t rectArea; - uint16_t dashWidth; +static void draw_pageIndicator(nbgl_page_indicator_t *obj, + nbgl_obj_t *prevObj, + bool computePosition) +{ + nbgl_area_t rectArea; + uint16_t dashWidth; - if (obj->nbPages <= NB_MAX_PAGES_WITH_DASHES) { - uint8_t i; -#define INTER_DASHES 10 // pixels - // force height - obj->obj.area.height = 4; + if (obj->nbPages <= NB_MAX_PAGES_WITH_DASHES) { + uint8_t i; +#define INTER_DASHES 10 // pixels + // force height + obj->obj.area.height = 4; - if (computePosition) { - compute_position((nbgl_obj_t *)obj,prevObj); - } - if (objDrawingDisabled) { - return; + if (computePosition) { + compute_position((nbgl_obj_t *) obj, prevObj); + } + if (objDrawingDisabled) { + return; + } + LOG_DEBUG(OBJ_LOGGER, + "draw_pageIndicator(), x0 = %d, y0 = %d, page = %d/%d\n", + obj->obj.area.x0, + obj->obj.area.y0, + obj->activePage, + obj->nbPages); + + // inherit background from parent + obj->obj.area.backgroundColor = obj->obj.parent->area.backgroundColor; + + dashWidth = (obj->obj.area.width - ((obj->nbPages - 1) * INTER_DASHES)) / obj->nbPages; + rectArea.x0 = obj->obj.area.x0; + rectArea.y0 = obj->obj.area.y0; + rectArea.width = dashWidth; + rectArea.height = obj->obj.area.height; + rectArea.backgroundColor = obj->obj.area.backgroundColor; + rectArea.bpp = NBGL_BPP_1; + // draw dashes + for (i = 0; i <= obj->activePage; i++) { + nbgl_frontDrawHorizontalLine(&rectArea, 0xF, BLACK); + rectArea.x0 += dashWidth + INTER_DASHES; + } + for (; i < obj->nbPages; i++) { + nbgl_frontDrawHorizontalLine(&rectArea, 0xF, LIGHT_GRAY); + rectArea.x0 += dashWidth + INTER_DASHES; + } } - LOG_DEBUG(OBJ_LOGGER,"draw_pageIndicator(), x0 = %d, y0 = %d, page = %d/%d\n", obj->obj.area.x0, obj->obj.area.y0, obj->activePage, obj->nbPages); + else { + char navText[11]; // worst case is "ccc of nnn" - // inherit background from parent - obj->obj.area.backgroundColor = obj->obj.parent->area.backgroundColor; + SPRINTF(navText, "%d of %d", obj->activePage + 1, obj->nbPages); + // force height + obj->obj.area.height = nbgl_getFontHeight(BAGL_FONT_INTER_REGULAR_24px); + // the width must be at least 80 + obj->obj.area.width = nbgl_getTextWidth(BAGL_FONT_INTER_REGULAR_24px, navText); - dashWidth = (obj->obj.area.width - ((obj->nbPages-1) * INTER_DASHES))/obj->nbPages; - rectArea.x0 = obj->obj.area.x0; - rectArea.y0 = obj->obj.area.y0; - rectArea.width = dashWidth; - rectArea.height = obj->obj.area.height; - rectArea.backgroundColor = obj->obj.area.backgroundColor; - rectArea.bpp = NBGL_BPP_1; - // draw dashes - for (i=0;i<=obj->activePage;i++) { - nbgl_frontDrawHorizontalLine(&rectArea, 0xF, BLACK); - rectArea.x0 += dashWidth+INTER_DASHES; - } - for (;inbPages;i++) { - nbgl_frontDrawHorizontalLine(&rectArea, 0xF, LIGHT_GRAY); - rectArea.x0 += dashWidth+INTER_DASHES; - } - } - else { - char navText[11]; // worst case is "ccc of nnn" - - SPRINTF(navText,"%d of %d", obj->activePage+1, obj->nbPages); - // force height - obj->obj.area.height = nbgl_getFontHeight(BAGL_FONT_INTER_REGULAR_24px); - // the width must be at least 80 - obj->obj.area.width = nbgl_getTextWidth(BAGL_FONT_INTER_REGULAR_24px,navText); - - if (computePosition) { - compute_position((nbgl_obj_t *)obj,prevObj); - } - if (objDrawingDisabled) { - return; + if (computePosition) { + compute_position((nbgl_obj_t *) obj, prevObj); + } + if (objDrawingDisabled) { + return; + } + LOG_DEBUG(OBJ_LOGGER, + "draw_pageIndicator(), x0 = %d, y0 = %d, page = %d/%d\n", + obj->obj.area.x0, + obj->obj.area.y0, + obj->activePage, + obj->nbPages); + + // inherit background from parent + obj->obj.area.backgroundColor = obj->obj.parent->area.backgroundColor; + + // draw active page + rectArea.x0 = obj->obj.area.x0; + rectArea.y0 = obj->obj.area.y0; + rectArea.width = obj->obj.area.width; + rectArea.height = obj->obj.area.height; + rectArea.backgroundColor = obj->obj.area.backgroundColor; + rectArea.bpp = NBGL_BPP_1; + nbgl_drawText(&rectArea, navText, 9, BAGL_FONT_INTER_REGULAR_24px, DARK_GRAY); } - LOG_DEBUG(OBJ_LOGGER,"draw_pageIndicator(), x0 = %d, y0 = %d, page = %d/%d\n", obj->obj.area.x0, obj->obj.area.y0, obj->activePage, obj->nbPages); - - // inherit background from parent - obj->obj.area.backgroundColor = obj->obj.parent->area.backgroundColor; - - // draw active page - rectArea.x0 = obj->obj.area.x0; - rectArea.y0 = obj->obj.area.y0; - rectArea.width = obj->obj.area.width; - rectArea.height = obj->obj.area.height; - rectArea.backgroundColor = obj->obj.area.backgroundColor; - rectArea.bpp = NBGL_BPP_1; - nbgl_drawText(&rectArea, navText, 9, BAGL_FONT_INTER_REGULAR_24px, DARK_GRAY); - } } /** @@ -622,156 +716,181 @@ static void draw_pageIndicator(nbgl_page_indicator_t* obj, nbgl_obj_t *prevObj, * @param prevObj the previous object drawned in the same container, with the default layout * @param computePosition if TRUE, force to compute the object position */ -static void draw_textArea(nbgl_text_area_t* obj, nbgl_obj_t *prevObj, bool computePosition) { - nbgl_area_t rectArea; - uint16_t textWidth,fontHeight,lineHeight, textHeight, midHeight; - uint8_t line,nbLines; - const char *text; - - if (computePosition) { - compute_position((nbgl_obj_t *)obj,prevObj); - } - if (objDrawingDisabled) { - return; - } - // get the text of the button from the callback if not NULL - if (obj->onDrawCallback != NULL) { - obj->text = obj->onDrawCallback(obj->token); - } - else { - if (obj->localized == true) { -#if defined(HAVE_LANGUAGE_PACK) - obj->text = get_ux_loc_string(obj->textId); -#endif // HAVE_LANGUAGE_PACK - } - } - text = obj->text; - if (text == NULL) { - return; - } - - LOG_DEBUG(OBJ_LOGGER,"draw_textArea(), wrapping = %d, x0 = %d, y0 = %d, width = %d, height = %d, text = %s\n", obj->wrapping, obj->obj.area.x0, obj->obj.area.y0, obj->obj.area.width, obj->obj.area.height, text); - - // inherit background from parent - obj->obj.area.backgroundColor = obj->obj.parent->area.backgroundColor; - - // draw background to make sure it's clean - rectArea.x0 = obj->obj.area.x0; - rectArea.y0 = obj->obj.area.y0; - rectArea.width = obj->obj.area.width; - rectArea.height = obj->obj.area.height; - rectArea.backgroundColor = obj->obj.area.backgroundColor; - nbgl_frontDrawRect(&rectArea); - // draw border with given style - if (obj->style == LEDGER_BORDER) { - // draw horizontal segments (4 pixels stroke) - rectArea.x0 = obj->obj.area.x0; - rectArea.y0 = obj->obj.area.y0; - rectArea.width = 24; - rectArea.height = 4; - nbgl_frontDrawHorizontalLine(&rectArea, 0xF, obj->textColor); // top left - rectArea.x0 = obj->obj.area.x0+obj->obj.area.width-rectArea.width; - nbgl_frontDrawHorizontalLine(&rectArea,0xF, obj->textColor); // top right - rectArea.y0 = obj->obj.area.y0+obj->obj.area.height-4; - nbgl_frontDrawHorizontalLine(&rectArea,0xF, obj->textColor); //bottom right - rectArea.x0 = obj->obj.area.x0; - nbgl_frontDrawHorizontalLine(&rectArea,0xF, obj->textColor); // bottom left - // draw vertical segments (4 pixels stroke) - rectArea.x0 = obj->obj.area.x0; - rectArea.y0 = obj->obj.area.y0+4; - rectArea.width = 4; - rectArea.height = 12; - rectArea.backgroundColor = obj->textColor; - nbgl_frontDrawRect(&rectArea); // top left - rectArea.x0 = obj->obj.area.x0+obj->obj.area.width-rectArea.width; - nbgl_frontDrawRect(&rectArea); // top right - rectArea.y0 = obj->obj.area.y0+obj->obj.area.height-rectArea.height-4; - nbgl_frontDrawRect(&rectArea); //bottom right - rectArea.x0 = obj->obj.area.x0; - nbgl_frontDrawRect(&rectArea); // bottom left - } - - fontHeight = nbgl_getFontHeight(obj->fontId); - lineHeight = nbgl_getFontLineHeight(obj->fontId); - // special case of autoHideLongLine, when the text is too long for a line, draw '...' at the beginning - if (obj->autoHideLongLine == true) { - textWidth = nbgl_getSingleLineTextWidth(obj->fontId,text); - if (textWidth > obj->obj.area.width) { - uint16_t lineWidth,lineLen; - uint16_t dotsWidth; - - // at first draw "..." at beginning - dotsWidth = nbgl_getTextWidth(obj->fontId,"..."); - rectArea.x0 = obj->obj.area.x0; - rectArea.y0 = obj->obj.area.y0 + (obj->obj.area.height - fontHeight)/2; - rectArea.width = dotsWidth; - nbgl_drawText(&rectArea, "...", 3, obj->fontId, obj->textColor); - // then draw the end of text - nbgl_getTextMaxLenAndWidthFromEnd(obj->fontId,text,obj->obj.area.width-dotsWidth,&lineLen,&lineWidth); - rectArea.x0 += dotsWidth; - rectArea.width = lineWidth; - nbgl_drawText(&rectArea, &text[nbgl_getTextLength(text)-lineLen], lineLen, obj->fontId, obj->textColor); - return; - } - } - - // get nb lines in the given width (depending of wrapping) - nbLines = nbgl_getTextNbLinesInWidth(obj->fontId,text,obj->obj.area.width,obj->wrapping); - // saturate nb lines if nbMaxLines is greater than 0 - if ((obj->nbMaxLines > 0) && (obj->nbMaxLines < nbLines)) { - nbLines = obj->nbMaxLines; - } - - textHeight = (nbLines-1)*lineHeight+fontHeight; - - midHeight = (obj->obj.area.height - textHeight)/2; - // Be sure midHeight is modulo 4 - if (midHeight % 4) { - midHeight -= midHeight % 4; - } - - rectArea.backgroundColor = obj->obj.area.backgroundColor; - rectArea.height = fontHeight; - // draw each line - for (line=0;linefontId,text,obj->obj.area.width,&lineLen,&lineWidth,obj->wrapping); - if (obj->textAlignment == MID_LEFT) { - rectArea.x0 = obj->obj.area.x0; - } - else if (obj->textAlignment == CENTER) { - rectArea.x0 = obj->obj.area.x0 + (obj->obj.area.width - lineWidth)/2; - } - else if (obj->textAlignment == MID_RIGHT) { - rectArea.x0 = obj->obj.area.x0 + obj->obj.area.width - lineWidth; +static void draw_textArea(nbgl_text_area_t *obj, nbgl_obj_t *prevObj, bool computePosition) +{ + nbgl_area_t rectArea; + uint16_t textWidth, fontHeight, lineHeight, textHeight, midHeight; + uint8_t line, nbLines; + const char *text; + + if (computePosition) { + compute_position((nbgl_obj_t *) obj, prevObj); + } + if (objDrawingDisabled) { + return; + } + // get the text of the button from the callback if not NULL + if (obj->onDrawCallback != NULL) { + obj->text = obj->onDrawCallback(obj->token); } else { - LOG_FATAL(OBJ_LOGGER,"Forbidden obj->textAlignment = %d\n",obj->textAlignment); + if (obj->localized == true) { +#if defined(HAVE_LANGUAGE_PACK) + obj->text = get_ux_loc_string(obj->textId); +#endif // HAVE_LANGUAGE_PACK + } + } + text = obj->text; + if (text == NULL) { + return; } - rectArea.y0 = obj->obj.area.y0 + midHeight + line*lineHeight; - rectArea.width = lineWidth; - LOG_DEBUG(OBJ_LOGGER,"draw_textArea(), %s line %d, lineLen %d lineWidth = %d, obj->obj.area.height = %d, textHeight = %d, obj->nbMaxLines = %d\n",text, line,lineLen, lineWidth,obj->obj.area.height, textHeight, obj->nbMaxLines); - if ((obj->nbMaxLines == 0) || (line < (obj->nbMaxLines-1))) { - nbgl_drawText(&rectArea, text, lineLen, obj->fontId, obj->textColor); + LOG_DEBUG( + OBJ_LOGGER, + "draw_textArea(), wrapping = %d, x0 = %d, y0 = %d, width = %d, height = %d, text = %s\n", + obj->wrapping, + obj->obj.area.x0, + obj->obj.area.y0, + obj->obj.area.width, + obj->obj.area.height, + text); + + // inherit background from parent + obj->obj.area.backgroundColor = obj->obj.parent->area.backgroundColor; + + // draw background to make sure it's clean + rectArea.x0 = obj->obj.area.x0; + rectArea.y0 = obj->obj.area.y0; + rectArea.width = obj->obj.area.width; + rectArea.height = obj->obj.area.height; + rectArea.backgroundColor = obj->obj.area.backgroundColor; + nbgl_frontDrawRect(&rectArea); + // draw border with given style + if (obj->style == LEDGER_BORDER) { + // draw horizontal segments (4 pixels stroke) + rectArea.x0 = obj->obj.area.x0; + rectArea.y0 = obj->obj.area.y0; + rectArea.width = 24; + rectArea.height = 4; + nbgl_frontDrawHorizontalLine(&rectArea, 0xF, obj->textColor); // top left + rectArea.x0 = obj->obj.area.x0 + obj->obj.area.width - rectArea.width; + nbgl_frontDrawHorizontalLine(&rectArea, 0xF, obj->textColor); // top right + rectArea.y0 = obj->obj.area.y0 + obj->obj.area.height - 4; + nbgl_frontDrawHorizontalLine(&rectArea, 0xF, obj->textColor); // bottom right + rectArea.x0 = obj->obj.area.x0; + nbgl_frontDrawHorizontalLine(&rectArea, 0xF, obj->textColor); // bottom left + // draw vertical segments (4 pixels stroke) + rectArea.x0 = obj->obj.area.x0; + rectArea.y0 = obj->obj.area.y0 + 4; + rectArea.width = 4; + rectArea.height = 12; + rectArea.backgroundColor = obj->textColor; + nbgl_frontDrawRect(&rectArea); // top left + rectArea.x0 = obj->obj.area.x0 + obj->obj.area.width - rectArea.width; + nbgl_frontDrawRect(&rectArea); // top right + rectArea.y0 = obj->obj.area.y0 + obj->obj.area.height - rectArea.height - 4; + nbgl_frontDrawRect(&rectArea); // bottom right + rectArea.x0 = obj->obj.area.x0; + nbgl_frontDrawRect(&rectArea); // bottom left + } + + fontHeight = nbgl_getFontHeight(obj->fontId); + lineHeight = nbgl_getFontLineHeight(obj->fontId); + // special case of autoHideLongLine, when the text is too long for a line, draw '...' at the + // beginning + if (obj->autoHideLongLine == true) { + textWidth = nbgl_getSingleLineTextWidth(obj->fontId, text); + if (textWidth > obj->obj.area.width) { + uint16_t lineWidth, lineLen; + uint16_t dotsWidth; + + // at first draw "..." at beginning + dotsWidth = nbgl_getTextWidth(obj->fontId, "..."); + rectArea.x0 = obj->obj.area.x0; + rectArea.y0 = obj->obj.area.y0 + (obj->obj.area.height - fontHeight) / 2; + rectArea.width = dotsWidth; + nbgl_drawText(&rectArea, "...", 3, obj->fontId, obj->textColor); + // then draw the end of text + nbgl_getTextMaxLenAndWidthFromEnd( + obj->fontId, text, obj->obj.area.width - dotsWidth, &lineLen, &lineWidth); + rectArea.x0 += dotsWidth; + rectArea.width = lineWidth; + nbgl_drawText(&rectArea, + &text[nbgl_getTextLength(text) - lineLen], + lineLen, + obj->fontId, + obj->textColor); + return; + } + } + + // get nb lines in the given width (depending of wrapping) + nbLines = nbgl_getTextNbLinesInWidth(obj->fontId, text, obj->obj.area.width, obj->wrapping); + // saturate nb lines if nbMaxLines is greater than 0 + if ((obj->nbMaxLines > 0) && (obj->nbMaxLines < nbLines)) { + nbLines = obj->nbMaxLines; + } + + textHeight = (nbLines - 1) * lineHeight + fontHeight; + + midHeight = (obj->obj.area.height - textHeight) / 2; + // Be sure midHeight is modulo 4 + if (midHeight % 4) { + midHeight -= midHeight % 4; + } + + rectArea.backgroundColor = obj->obj.area.backgroundColor; + rectArea.height = fontHeight; + // draw each line + for (line = 0; line < nbLines; line++) { + uint16_t lineWidth, lineLen; + + nbgl_getTextMaxLenAndWidth( + obj->fontId, text, obj->obj.area.width, &lineLen, &lineWidth, obj->wrapping); + if (obj->textAlignment == MID_LEFT) { + rectArea.x0 = obj->obj.area.x0; + } + else if (obj->textAlignment == CENTER) { + rectArea.x0 = obj->obj.area.x0 + (obj->obj.area.width - lineWidth) / 2; + } + else if (obj->textAlignment == MID_RIGHT) { + rectArea.x0 = obj->obj.area.x0 + obj->obj.area.width - lineWidth; + } + else { + LOG_FATAL(OBJ_LOGGER, "Forbidden obj->textAlignment = %d\n", obj->textAlignment); + } + rectArea.y0 = obj->obj.area.y0 + midHeight + line * lineHeight; + rectArea.width = lineWidth; + + LOG_DEBUG(OBJ_LOGGER, + "draw_textArea(), %s line %d, lineLen %d lineWidth = %d, obj->obj.area.height = " + "%d, textHeight = %d, obj->nbMaxLines = %d\n", + text, + line, + lineLen, + lineWidth, + obj->obj.area.height, + textHeight, + obj->nbMaxLines); + if ((obj->nbMaxLines == 0) || (line < (obj->nbMaxLines - 1))) { + nbgl_drawText(&rectArea, text, lineLen, obj->fontId, obj->textColor); + } + else { + // for last chunk, if nbMaxLines is used, replace the 3 last chars by "..." + // draw line except 3 last chars + nbgl_drawText(&rectArea, text, lineLen - 3, obj->fontId, obj->textColor); + // draw "..." after the other chars + rectArea.x0 += nbgl_getSingleLineTextWidthInLen(obj->fontId, text, lineLen - 3); + rectArea.width = nbgl_getSingleLineTextWidth(obj->fontId, "..."); + nbgl_drawText(&rectArea, "...", 3, obj->fontId, obj->textColor); + return; + } + text += lineLen; + /* skip trailing \n */ + if (*text == '\n') { + text++; + } } - else { - // for last chunk, if nbMaxLines is used, replace the 3 last chars by "..." - // draw line except 3 last chars - nbgl_drawText(&rectArea, text, lineLen-3, obj->fontId, obj->textColor); - // draw "..." after the other chars - rectArea.x0 += nbgl_getSingleLineTextWidthInLen(obj->fontId, text, lineLen-3); - rectArea.width = nbgl_getSingleLineTextWidth(obj->fontId,"..."); - nbgl_drawText(&rectArea, "...", 3, obj->fontId, obj->textColor); - return; - } - text += lineLen; - /* skip trailing \n */ - if (*text == '\n') { - text++; - } - } } /** @@ -782,29 +901,36 @@ static void draw_textArea(nbgl_text_area_t* obj, nbgl_obj_t *prevObj, bool compu * @param prevObj the previous object drawned in the same container, with the default layout * @param computePosition if TRUE, force to compute the object position */ -static void draw_qrCode(nbgl_qrcode_t* obj, nbgl_obj_t *prevObj, bool computePosition) { - nbgl_area_t rectArea; - - if (computePosition) { - compute_position((nbgl_obj_t *)obj,prevObj); - } - if (objDrawingDisabled) { - return; - } - LOG_DEBUG(OBJ_LOGGER,"draw_qrCode(), x0 = %d, y0 = %d, width = %d, height = %d, text = %s\n", obj->obj.area.x0, obj->obj.area.y0, obj->obj.area.width, obj->obj.area.height, obj->text); - - // inherit background from parent - obj->obj.area.backgroundColor = obj->obj.parent->area.backgroundColor; - - rectArea.x0 = obj->obj.area.x0; - rectArea.y0 = obj->obj.area.y0; - rectArea.width = obj->obj.area.width; - rectArea.height = obj->obj.area.height; - rectArea.backgroundColor = obj->obj.area.backgroundColor; -#ifdef NBGL_QRCODE - nbgl_drawQrCode(&rectArea,(obj->version == QRCODE_V4) ? 4:10,obj->text,obj->foregroundColor); -#endif // NBGL_QRCODE +static void draw_qrCode(nbgl_qrcode_t *obj, nbgl_obj_t *prevObj, bool computePosition) +{ + nbgl_area_t rectArea; + if (computePosition) { + compute_position((nbgl_obj_t *) obj, prevObj); + } + if (objDrawingDisabled) { + return; + } + LOG_DEBUG(OBJ_LOGGER, + "draw_qrCode(), x0 = %d, y0 = %d, width = %d, height = %d, text = %s\n", + obj->obj.area.x0, + obj->obj.area.y0, + obj->obj.area.width, + obj->obj.area.height, + obj->text); + + // inherit background from parent + obj->obj.area.backgroundColor = obj->obj.parent->area.backgroundColor; + + rectArea.x0 = obj->obj.area.x0; + rectArea.y0 = obj->obj.area.y0; + rectArea.width = obj->obj.area.width; + rectArea.height = obj->obj.area.height; + rectArea.backgroundColor = obj->obj.area.backgroundColor; +#ifdef NBGL_QRCODE + nbgl_drawQrCode( + &rectArea, (obj->version == QRCODE_V4) ? 4 : 10, obj->text, obj->foregroundColor); +#endif // NBGL_QRCODE } /** @@ -814,28 +940,29 @@ static void draw_qrCode(nbgl_qrcode_t* obj, nbgl_obj_t *prevObj, bool computePos * @param prevObj the previous object drawned in the same container, with the default layout * @param computePosition if TRUE, force to compute the object position */ -static void draw_keyboard(nbgl_keyboard_t* obj, nbgl_obj_t *prevObj, bool computePosition) { - obj->obj.area.width = SCREEN_WIDTH; - obj->obj.area.height = 3*KEYBOARD_KEY_HEIGHT; - if (!obj->lettersOnly) { - obj->obj.area.height += KEYBOARD_KEY_HEIGHT; - } - - if (computePosition) { - compute_position((nbgl_obj_t *)obj,prevObj); - } - if (objDrawingDisabled) { - return; - } - LOG_DEBUG(OBJ_LOGGER,"draw_keyboard(), x0 = %d, y0 = %d\n", obj->obj.area.x0, obj->obj.area.y0); - - // inherit background from parent - obj->obj.area.backgroundColor = obj->obj.parent->area.backgroundColor; +static void draw_keyboard(nbgl_keyboard_t *obj, nbgl_obj_t *prevObj, bool computePosition) +{ + obj->obj.area.width = SCREEN_WIDTH; + obj->obj.area.height = 3 * KEYBOARD_KEY_HEIGHT; + if (!obj->lettersOnly) { + obj->obj.area.height += KEYBOARD_KEY_HEIGHT; + } -#ifdef NBGL_KEYBOARD - nbgl_objDrawKeyboard(obj); -#endif // NBGL_KEYBOARD + if (computePosition) { + compute_position((nbgl_obj_t *) obj, prevObj); + } + if (objDrawingDisabled) { + return; + } + LOG_DEBUG( + OBJ_LOGGER, "draw_keyboard(), x0 = %d, y0 = %d\n", obj->obj.area.x0, obj->obj.area.y0); + // inherit background from parent + obj->obj.area.backgroundColor = obj->obj.parent->area.backgroundColor; + +#ifdef NBGL_KEYBOARD + nbgl_objDrawKeyboard(obj); +#endif // NBGL_KEYBOARD } /** @@ -845,25 +972,25 @@ static void draw_keyboard(nbgl_keyboard_t* obj, nbgl_obj_t *prevObj, bool comput * @param prevObj the previous object drawned in the same container, with the default layout * @param computePosition if TRUE, force to compute the object position */ -static void draw_keypad(nbgl_keypad_t* obj, nbgl_obj_t *prevObj, bool computePosition) { - obj->obj.area.width = SCREEN_WIDTH; - obj->obj.area.height = 4*KEYPAD_KEY_HEIGHT; +static void draw_keypad(nbgl_keypad_t *obj, nbgl_obj_t *prevObj, bool computePosition) +{ + obj->obj.area.width = SCREEN_WIDTH; + obj->obj.area.height = 4 * KEYPAD_KEY_HEIGHT; - if (computePosition) { - compute_position((nbgl_obj_t *)obj,prevObj); - } - if (objDrawingDisabled) { - return; - } - LOG_DEBUG(OBJ_LOGGER,"draw_keypad(), x0 = %d, y0 = %d\n", obj->obj.area.x0, obj->obj.area.y0); + if (computePosition) { + compute_position((nbgl_obj_t *) obj, prevObj); + } + if (objDrawingDisabled) { + return; + } + LOG_DEBUG(OBJ_LOGGER, "draw_keypad(), x0 = %d, y0 = %d\n", obj->obj.area.x0, obj->obj.area.y0); - // inherit background from parent - obj->obj.area.backgroundColor = obj->obj.parent->area.backgroundColor; + // inherit background from parent + obj->obj.area.backgroundColor = obj->obj.parent->area.backgroundColor; #ifdef NBGL_KEYPAD - nbgl_objDrawKeypad(obj); -#endif // NBGL_KEYPAD - + nbgl_objDrawKeypad(obj); +#endif // NBGL_KEYPAD } /** @@ -873,121 +1000,122 @@ static void draw_keypad(nbgl_keypad_t* obj, nbgl_obj_t *prevObj, bool computePos * @param prevObj the previous object drawned in the same container, with the default layout * @param computePosition if TRUE, force to compute the object position */ -static void draw_spinner(nbgl_spinner_t* obj, nbgl_obj_t *prevObj, bool computePosition) { - nbgl_area_t rectArea; - color_t foreColor; - - obj->obj.area.width = 60; - obj->obj.area.height = 44; - - if (computePosition) { - compute_position((nbgl_obj_t *)obj,prevObj); - } - if (objDrawingDisabled) { - return; - } - LOG_DEBUG(OBJ_LOGGER,"draw_spinner(), x0 = %d, y0 = %d\n", obj->obj.area.x0, obj->obj.area.y0); - - // inherit background from parent - obj->obj.area.backgroundColor = obj->obj.parent->area.backgroundColor; - // foreground color is the opposite of background one - foreColor = (obj->obj.area.backgroundColor == WHITE) ? BLACK : WHITE; - - rectArea.bpp = NBGL_BPP_1; - rectArea.backgroundColor = obj->obj.area.backgroundColor; - // if position is OxFF, it means "fixed" so draw 4 corners - if (obj->position == 0xFF) { - // draw horizontal segments - rectArea.x0 = obj->obj.area.x0; - rectArea.y0 = obj->obj.area.y0; - rectArea.width = 20; - rectArea.height = 4; - nbgl_frontDrawHorizontalLine(&rectArea, 0x7, foreColor); // top left - rectArea.x0 = obj->obj.area.x0+obj->obj.area.width-rectArea.width; - nbgl_frontDrawHorizontalLine(&rectArea,0x7, foreColor); // top right - rectArea.y0 = obj->obj.area.y0+obj->obj.area.height-4; - nbgl_frontDrawHorizontalLine(&rectArea,0xE, foreColor); //bottom right - rectArea.x0 = obj->obj.area.x0; - nbgl_frontDrawHorizontalLine(&rectArea,0xE, foreColor); // bottom left - // draw vertical segments - rectArea.x0 = obj->obj.area.x0; - rectArea.y0 = obj->obj.area.y0; - rectArea.width = 3; - rectArea.height = 12; - rectArea.backgroundColor = foreColor; - nbgl_frontDrawRect(&rectArea); // top left - rectArea.x0 = obj->obj.area.x0+obj->obj.area.width-rectArea.width; - nbgl_frontDrawRect(&rectArea); // top right - rectArea.y0 = obj->obj.area.y0+obj->obj.area.height-rectArea.height; - nbgl_frontDrawRect(&rectArea); //bottom right - rectArea.x0 = obj->obj.area.x0; - nbgl_frontDrawRect(&rectArea); // bottom left - } - else { - uint8_t mask; - // clean up full rectangle - rectArea.x0 = obj->obj.area.x0; - rectArea.y0 = obj->obj.area.y0; - rectArea.width = obj->obj.area.width; - rectArea.height = obj->obj.area.height; +static void draw_spinner(nbgl_spinner_t *obj, nbgl_obj_t *prevObj, bool computePosition) +{ + nbgl_area_t rectArea; + color_t foreColor; + + obj->obj.area.width = 60; + obj->obj.area.height = 44; + + if (computePosition) { + compute_position((nbgl_obj_t *) obj, prevObj); + } + if (objDrawingDisabled) { + return; + } + LOG_DEBUG(OBJ_LOGGER, "draw_spinner(), x0 = %d, y0 = %d\n", obj->obj.area.x0, obj->obj.area.y0); + + // inherit background from parent + obj->obj.area.backgroundColor = obj->obj.parent->area.backgroundColor; + // foreground color is the opposite of background one + foreColor = (obj->obj.area.backgroundColor == WHITE) ? BLACK : WHITE; + + rectArea.bpp = NBGL_BPP_1; rectArea.backgroundColor = obj->obj.area.backgroundColor; - nbgl_frontDrawRect(&rectArea); // top left - - // draw horizontal segment in foreColor - rectArea.width = 20; - rectArea.height = 4; - switch (obj->position) { - case 0: // top left corner - rectArea.x0 = obj->obj.area.x0; - rectArea.y0 = obj->obj.area.y0; - mask = 0x7; - break; - case 1: // top right - rectArea.x0 = obj->obj.area.x0+obj->obj.area.width-rectArea.width; - rectArea.y0 = obj->obj.area.y0; - mask = 0x7; - break; - case 2: //bottom right - rectArea.x0 = obj->obj.area.x0+obj->obj.area.width-rectArea.width; - rectArea.y0 = obj->obj.area.y0+obj->obj.area.height-4; - mask = 0xE; - break; - case 3: // bottom left - rectArea.x0 = obj->obj.area.x0; - rectArea.y0 = obj->obj.area.y0+obj->obj.area.height-4; - mask = 0xE; - break; - default: - return; - } - nbgl_frontDrawHorizontalLine(&rectArea, mask, foreColor); - - // draw vertical segment in foreColor - rectArea.width = 3; - rectArea.height = 12; - rectArea.backgroundColor = foreColor; - switch (obj->position) { - case 0:// top left corner - rectArea.x0 = obj->obj.area.x0; - rectArea.y0 = obj->obj.area.y0; - break; - case 1:// top right corner - rectArea.x0 = obj->obj.area.x0+obj->obj.area.width-rectArea.width; - rectArea.y0 = obj->obj.area.y0; - break; - case 2:// bottom right corner - rectArea.x0 = obj->obj.area.x0+obj->obj.area.width-rectArea.width; - rectArea.y0 = obj->obj.area.y0+obj->obj.area.height-rectArea.height; - break; - case 3:// bottom left corner - rectArea.x0 = obj->obj.area.x0; - rectArea.y0 = obj->obj.area.y0+obj->obj.area.height-rectArea.height; - break; - default: - return; + // if position is OxFF, it means "fixed" so draw 4 corners + if (obj->position == 0xFF) { + // draw horizontal segments + rectArea.x0 = obj->obj.area.x0; + rectArea.y0 = obj->obj.area.y0; + rectArea.width = 20; + rectArea.height = 4; + nbgl_frontDrawHorizontalLine(&rectArea, 0x7, foreColor); // top left + rectArea.x0 = obj->obj.area.x0 + obj->obj.area.width - rectArea.width; + nbgl_frontDrawHorizontalLine(&rectArea, 0x7, foreColor); // top right + rectArea.y0 = obj->obj.area.y0 + obj->obj.area.height - 4; + nbgl_frontDrawHorizontalLine(&rectArea, 0xE, foreColor); // bottom right + rectArea.x0 = obj->obj.area.x0; + nbgl_frontDrawHorizontalLine(&rectArea, 0xE, foreColor); // bottom left + // draw vertical segments + rectArea.x0 = obj->obj.area.x0; + rectArea.y0 = obj->obj.area.y0; + rectArea.width = 3; + rectArea.height = 12; + rectArea.backgroundColor = foreColor; + nbgl_frontDrawRect(&rectArea); // top left + rectArea.x0 = obj->obj.area.x0 + obj->obj.area.width - rectArea.width; + nbgl_frontDrawRect(&rectArea); // top right + rectArea.y0 = obj->obj.area.y0 + obj->obj.area.height - rectArea.height; + nbgl_frontDrawRect(&rectArea); // bottom right + rectArea.x0 = obj->obj.area.x0; + nbgl_frontDrawRect(&rectArea); // bottom left + } + else { + uint8_t mask; + // clean up full rectangle + rectArea.x0 = obj->obj.area.x0; + rectArea.y0 = obj->obj.area.y0; + rectArea.width = obj->obj.area.width; + rectArea.height = obj->obj.area.height; + rectArea.backgroundColor = obj->obj.area.backgroundColor; + nbgl_frontDrawRect(&rectArea); // top left + + // draw horizontal segment in foreColor + rectArea.width = 20; + rectArea.height = 4; + switch (obj->position) { + case 0: // top left corner + rectArea.x0 = obj->obj.area.x0; + rectArea.y0 = obj->obj.area.y0; + mask = 0x7; + break; + case 1: // top right + rectArea.x0 = obj->obj.area.x0 + obj->obj.area.width - rectArea.width; + rectArea.y0 = obj->obj.area.y0; + mask = 0x7; + break; + case 2: // bottom right + rectArea.x0 = obj->obj.area.x0 + obj->obj.area.width - rectArea.width; + rectArea.y0 = obj->obj.area.y0 + obj->obj.area.height - 4; + mask = 0xE; + break; + case 3: // bottom left + rectArea.x0 = obj->obj.area.x0; + rectArea.y0 = obj->obj.area.y0 + obj->obj.area.height - 4; + mask = 0xE; + break; + default: + return; + } + nbgl_frontDrawHorizontalLine(&rectArea, mask, foreColor); + + // draw vertical segment in foreColor + rectArea.width = 3; + rectArea.height = 12; + rectArea.backgroundColor = foreColor; + switch (obj->position) { + case 0: // top left corner + rectArea.x0 = obj->obj.area.x0; + rectArea.y0 = obj->obj.area.y0; + break; + case 1: // top right corner + rectArea.x0 = obj->obj.area.x0 + obj->obj.area.width - rectArea.width; + rectArea.y0 = obj->obj.area.y0; + break; + case 2: // bottom right corner + rectArea.x0 = obj->obj.area.x0 + obj->obj.area.width - rectArea.width; + rectArea.y0 = obj->obj.area.y0 + obj->obj.area.height - rectArea.height; + break; + case 3: // bottom left corner + rectArea.x0 = obj->obj.area.x0; + rectArea.y0 = obj->obj.area.y0 + obj->obj.area.height - rectArea.height; + break; + default: + return; + } + nbgl_frontDrawRect(&rectArea); } - nbgl_frontDrawRect(&rectArea); - } } /** @@ -997,19 +1125,21 @@ static void draw_spinner(nbgl_spinner_t* obj, nbgl_obj_t *prevObj, bool computeP * @param prevObj the previous object drawned in the same container, with the default layout * @param computePosition if TRUE, force to compute the object position */ -static void draw_image_file(nbgl_image_file_t* obj, nbgl_obj_t *prevObj, bool computePosition) { - if (obj->buffer == NULL) { - return; - } - if (computePosition) { - compute_position((nbgl_obj_t *)obj,prevObj); - } - if (objDrawingDisabled) { - return; - } - - LOG_DEBUG(OBJ_LOGGER,"draw_image_file(), x0 = %d, y0 = %d\n", obj->obj.area.x0, obj->obj.area.y0); - nbgl_frontDrawImageFile((nbgl_area_t *)obj, (uint8_t*)obj->buffer, 0, ramBuffer); +static void draw_image_file(nbgl_image_file_t *obj, nbgl_obj_t *prevObj, bool computePosition) +{ + if (obj->buffer == NULL) { + return; + } + if (computePosition) { + compute_position((nbgl_obj_t *) obj, prevObj); + } + if (objDrawingDisabled) { + return; + } + + LOG_DEBUG( + OBJ_LOGGER, "draw_image_file(), x0 = %d, y0 = %d\n", obj->obj.area.x0, obj->obj.area.y0); + nbgl_frontDrawImageFile((nbgl_area_t *) obj, (uint8_t *) obj->buffer, 0, ramBuffer); } /** @@ -1024,211 +1154,244 @@ static void draw_image_file(nbgl_image_file_t* obj, nbgl_obj_t *prevObj, bool co __attribute__((optimize("O0"))) #endif #endif -static void draw_object(nbgl_obj_t *obj, nbgl_obj_t *prevObj, bool computePosition) { - LOG_DEBUG(OBJ_LOGGER,"draw_object() obj->type = %d, prevObj = %p\n",obj->type,prevObj); - switch (obj->type) { - case SCREEN: - draw_screen((nbgl_container_t*)obj); - break; - case CONTAINER: - draw_container((nbgl_container_t*)obj, prevObj, computePosition); - break; - case BUTTON: - draw_button((nbgl_button_t*)obj, prevObj, computePosition); - break; - case LINE: - draw_line((nbgl_line_t*)obj, prevObj, computePosition); - break; - case IMAGE: - draw_image((nbgl_image_t*)obj, prevObj, computePosition); - break; - case SWITCH: - draw_switch((nbgl_switch_t*)obj, prevObj, computePosition); - break; - case RADIO_BUTTON: - draw_radioButton((nbgl_radio_t*)obj, prevObj, computePosition); - break; - case PROGRESS_BAR: - draw_progressBar((nbgl_progress_bar_t*)obj, prevObj, computePosition); - break; - case PAGE_INDICATOR: - draw_pageIndicator((nbgl_page_indicator_t*)obj, prevObj, computePosition); - break; - case TEXT_AREA: - draw_textArea((nbgl_text_area_t*)obj, prevObj, computePosition); - break; - case QR_CODE: - draw_qrCode((nbgl_qrcode_t*)obj, prevObj, computePosition); - break; - case KEYBOARD: - draw_keyboard((nbgl_keyboard_t*)obj, prevObj, computePosition); - break; - case KEYPAD: - draw_keypad((nbgl_keypad_t*)obj, prevObj, computePosition); - break; - case SPINNER: - draw_spinner((nbgl_spinner_t*)obj, prevObj, computePosition); - break; - case IMAGE_FILE: - draw_image_file((nbgl_image_file_t*)obj, prevObj, computePosition); - break; - default: - LOG_DEBUG(OBJ_LOGGER,"Not existing object type\n"); - break; - } - - #ifdef HAVE_SERIALIZED_NBGL - io_seproxyhal_send_nbgl_serialized(NBGL_DRAW_OBJ, obj); - #endif - if (!objDrawingDisabled) { - extendRefreshArea(obj); - } +static void +draw_object(nbgl_obj_t *obj, nbgl_obj_t *prevObj, bool computePosition) +{ + LOG_DEBUG(OBJ_LOGGER, "draw_object() obj->type = %d, prevObj = %p\n", obj->type, prevObj); + switch (obj->type) { + case SCREEN: + draw_screen((nbgl_container_t *) obj); + break; + case CONTAINER: + draw_container((nbgl_container_t *) obj, prevObj, computePosition); + break; + case BUTTON: + draw_button((nbgl_button_t *) obj, prevObj, computePosition); + break; + case LINE: + draw_line((nbgl_line_t *) obj, prevObj, computePosition); + break; + case IMAGE: + draw_image((nbgl_image_t *) obj, prevObj, computePosition); + break; + case SWITCH: + draw_switch((nbgl_switch_t *) obj, prevObj, computePosition); + break; + case RADIO_BUTTON: + draw_radioButton((nbgl_radio_t *) obj, prevObj, computePosition); + break; + case PROGRESS_BAR: + draw_progressBar((nbgl_progress_bar_t *) obj, prevObj, computePosition); + break; + case PAGE_INDICATOR: + draw_pageIndicator((nbgl_page_indicator_t *) obj, prevObj, computePosition); + break; + case TEXT_AREA: + draw_textArea((nbgl_text_area_t *) obj, prevObj, computePosition); + break; + case QR_CODE: + draw_qrCode((nbgl_qrcode_t *) obj, prevObj, computePosition); + break; + case KEYBOARD: + draw_keyboard((nbgl_keyboard_t *) obj, prevObj, computePosition); + break; + case KEYPAD: + draw_keypad((nbgl_keypad_t *) obj, prevObj, computePosition); + break; + case SPINNER: + draw_spinner((nbgl_spinner_t *) obj, prevObj, computePosition); + break; + case IMAGE_FILE: + draw_image_file((nbgl_image_file_t *) obj, prevObj, computePosition); + break; + default: + LOG_DEBUG(OBJ_LOGGER, "Not existing object type\n"); + break; + } +#ifdef HAVE_SERIALIZED_NBGL + io_seproxyhal_send_nbgl_serialized(NBGL_DRAW_OBJ, obj); +#endif + if (!objDrawingDisabled) { + extendRefreshArea(obj); + } } /** - * @brief internal function used when an object is drawn, to extend the area to be refresh in display + * @brief internal function used when an object is drawn, to extend the area to be refresh in + * display * * @param obj the object drawn */ -void extendRefreshArea(nbgl_obj_t *obj) { - uint16_t x1,y1; // bottom right corner - x1 = refreshArea.x0+refreshArea.width; - y1 = refreshArea.y0+refreshArea.height; - - // if obj top-left is on left of current top-left corner, move top-left corner - if (obj->area.x0 < refreshArea.x0) { - refreshArea.x0 = obj->area.x0; - } - // if obj bottom-right is on right of current bottom-right corner, move bottom-right corner - if (((obj->area.x0+obj->area.width) > x1) || (refreshArea.width == 0)) { - x1 = obj->area.x0+obj->area.width; - } - // if obj top-left is on top of current top-left corner, move top-left corner - if (obj->area.y0 < refreshArea.y0) { - refreshArea.y0 = obj->area.y0; - } - // if obj bottom-right is on bottom of current bottom-right corner, move bottom-right corner - if (((obj->area.y0+obj->area.height) > y1) || (refreshArea.height == 0)) { - y1 = obj->area.y0+obj->area.height; - } - - // sanity check - if (x1 > SCREEN_WIDTH) { - LOG_FATAL(OBJ_LOGGER,"extendRefreshArea: Impossible area x0 = %d width %d\n",refreshArea.x0,refreshArea.width); - } - if (y1 > SCREEN_HEIGHT) { - LOG_FATAL(OBJ_LOGGER,"extendRefreshArea: Impossible area y0 = %d height %d\n",refreshArea.y0,refreshArea.height); - } - // recompute width and height - refreshArea.width = x1 - refreshArea.x0; - refreshArea.height = y1 - refreshArea.y0; - - // revaluate area bpp - if (obj->area.bpp > refreshArea.bpp) { - refreshArea.bpp = obj->area.bpp; - } +void extendRefreshArea(nbgl_obj_t *obj) +{ + uint16_t x1, y1; // bottom right corner + x1 = refreshArea.x0 + refreshArea.width; + y1 = refreshArea.y0 + refreshArea.height; + + // if obj top-left is on left of current top-left corner, move top-left corner + if (obj->area.x0 < refreshArea.x0) { + refreshArea.x0 = obj->area.x0; + } + // if obj bottom-right is on right of current bottom-right corner, move bottom-right corner + if (((obj->area.x0 + obj->area.width) > x1) || (refreshArea.width == 0)) { + x1 = obj->area.x0 + obj->area.width; + } + // if obj top-left is on top of current top-left corner, move top-left corner + if (obj->area.y0 < refreshArea.y0) { + refreshArea.y0 = obj->area.y0; + } + // if obj bottom-right is on bottom of current bottom-right corner, move bottom-right corner + if (((obj->area.y0 + obj->area.height) > y1) || (refreshArea.height == 0)) { + y1 = obj->area.y0 + obj->area.height; + } + + // sanity check + if (x1 > SCREEN_WIDTH) { + LOG_FATAL(OBJ_LOGGER, + "extendRefreshArea: Impossible area x0 = %d width %d\n", + refreshArea.x0, + refreshArea.width); + } + if (y1 > SCREEN_HEIGHT) { + LOG_FATAL(OBJ_LOGGER, + "extendRefreshArea: Impossible area y0 = %d height %d\n", + refreshArea.y0, + refreshArea.height); + } + // recompute width and height + refreshArea.width = x1 - refreshArea.x0; + refreshArea.height = y1 - refreshArea.y0; + + // revaluate area bpp + if (obj->area.bpp > refreshArea.bpp) { + refreshArea.bpp = obj->area.bpp; + } } /** * @brief This function redraws the given object and its children (recursive version) * * @param obj the object to redraw - * @param prevObj the previous child of this object in the parent's children array (may be NULL for first element of the array) - * @param computePosition if set to true, means that the position of the object will be recomputed (needs prevObj if alignment on this object) + * @param prevObj the previous child of this object in the parent's children array (may be NULL for + * first element of the array) + * @param computePosition if set to true, means that the position of the object will be recomputed + * (needs prevObj if alignment on this object) */ -void nbgl_redrawObject(nbgl_obj_t *obj, nbgl_obj_t *prevObj, bool computePosition) { - uint8_t i=0; - LOG_DEBUG(OBJ_LOGGER,"nbgl_redrawObject(): obj = %p\n",obj); - // draw the object itself - draw_object(obj,prevObj,computePosition); - - if ((obj->type == SCREEN) || - (obj->type == CONTAINER)) { - nbgl_container_t *container = (nbgl_container_t *)obj; - nbgl_obj_t *prev = NULL; - LOG_DEBUG(OBJ_LOGGER,"nbgl_redrawObject(): container->children = %p\n",container->children); - // draw the children, if any - if (container->children != NULL) { - for (i=0;inbChildren;i++) { - nbgl_obj_t *current = container->children[i]; - if (current!= NULL) { - current->parent = (nbgl_obj_t *)container; - nbgl_redrawObject(current,prev,true); - if (current->alignTo == NULL) - prev = current; +void nbgl_redrawObject(nbgl_obj_t *obj, nbgl_obj_t *prevObj, bool computePosition) +{ + uint8_t i = 0; + LOG_DEBUG(OBJ_LOGGER, "nbgl_redrawObject(): obj = %p\n", obj); + // draw the object itself + draw_object(obj, prevObj, computePosition); + + if ((obj->type == SCREEN) || (obj->type == CONTAINER)) { + nbgl_container_t *container = (nbgl_container_t *) obj; + nbgl_obj_t *prev = NULL; + LOG_DEBUG( + OBJ_LOGGER, "nbgl_redrawObject(): container->children = %p\n", container->children); + // draw the children, if any + if (container->children != NULL) { + for (i = 0; i < container->nbChildren; i++) { + nbgl_obj_t *current = container->children[i]; + if (current != NULL) { + current->parent = (nbgl_obj_t *) container; + nbgl_redrawObject(current, prev, true); + if (current->alignTo == NULL) { + prev = current; + } + } + } } - } } - } } /** - * @brief This functions refreshes the actual screen on display with what has changed since the last refresh + * @brief This functions refreshes the actual screen on display with what has changed since the last + * refresh * */ -void nbgl_refresh(void) { - nbgl_refreshSpecial(FULL_COLOR_CLEAN_REFRESH); +void nbgl_refresh(void) +{ + nbgl_refreshSpecial(FULL_COLOR_CLEAN_REFRESH); } /** - * @brief This functions refreshes the actual screen on display with what has changed since the last refresh, - * according to the given mode (Black&White and other) + * @brief This functions refreshes the actual screen on display with what has changed since the last + * refresh, according to the given mode (Black&White and other) * @param mode mode of refresh */ -void nbgl_refreshSpecial(nbgl_refresh_mode_t mode) { - if ((refreshArea.width == 0) || (refreshArea.height == 0)) - return; - - #ifdef HAVE_SERIALIZED_NBGL - io_seproxyhal_send_nbgl_serialized(NBGL_REFRESH_AREA, (nbgl_obj_t *) &refreshArea); - #endif - nbgl_frontRefreshArea(&refreshArea, mode, POST_REFRESH_FORCE_POWER_OFF); - LOG_DEBUG(OBJ_LOGGER,"nbgl_refreshSpecial(), x0,y0 = [%d, %d], w,h = [%d, %d]\n", refreshArea.x0, refreshArea.y0, refreshArea.width, refreshArea.height); - nbgl_refreshReset(); +void nbgl_refreshSpecial(nbgl_refresh_mode_t mode) +{ + if ((refreshArea.width == 0) || (refreshArea.height == 0)) { + return; + } + +#ifdef HAVE_SERIALIZED_NBGL + io_seproxyhal_send_nbgl_serialized(NBGL_REFRESH_AREA, (nbgl_obj_t *) &refreshArea); +#endif + nbgl_frontRefreshArea(&refreshArea, mode, POST_REFRESH_FORCE_POWER_OFF); + LOG_DEBUG(OBJ_LOGGER, + "nbgl_refreshSpecial(), x0,y0 = [%d, %d], w,h = [%d, %d]\n", + refreshArea.x0, + refreshArea.y0, + refreshArea.width, + refreshArea.height); + nbgl_refreshReset(); } -void nbgl_refreshSpecialWithPostRefresh(nbgl_refresh_mode_t mode, nbgl_post_refresh_t post_refresh) { - if ((refreshArea.width == 0) || (refreshArea.height == 0)) - return; +void nbgl_refreshSpecialWithPostRefresh(nbgl_refresh_mode_t mode, nbgl_post_refresh_t post_refresh) +{ + if ((refreshArea.width == 0) || (refreshArea.height == 0)) { + return; + } - #ifdef HAVE_SERIALIZED_NBGL - io_seproxyhal_send_nbgl_serialized(NBGL_REFRESH_AREA, (nbgl_obj_t *) &refreshArea); - #endif - nbgl_frontRefreshArea(&refreshArea, mode, post_refresh); - LOG_DEBUG(OBJ_LOGGER,"nbgl_refreshSpecialNoPoff(), x0,y0 = [%d, %d], w,h = [%d, %d]\n", refreshArea.x0, refreshArea.y0, refreshArea.width, refreshArea.height); - nbgl_refreshReset(); +#ifdef HAVE_SERIALIZED_NBGL + io_seproxyhal_send_nbgl_serialized(NBGL_REFRESH_AREA, (nbgl_obj_t *) &refreshArea); +#endif + nbgl_frontRefreshArea(&refreshArea, mode, post_refresh); + LOG_DEBUG(OBJ_LOGGER, + "nbgl_refreshSpecialNoPoff(), x0,y0 = [%d, %d], w,h = [%d, %d]\n", + refreshArea.x0, + refreshArea.y0, + refreshArea.width, + refreshArea.height); + nbgl_refreshReset(); } /** * @brief This functions returns true if there is something to refresh * @return true if there is something to refresh */ -bool nbgl_refreshIsNeeded(void) { - if ((refreshArea.width == 0) || (refreshArea.height == 0)) - return false; - return true; +bool nbgl_refreshIsNeeded(void) +{ + if ((refreshArea.width == 0) || (refreshArea.height == 0)) { + return false; + } + return true; } /** * @brief This functions resets all changes since the last refresh * */ -void nbgl_refreshReset(void) { - refreshArea.x0 = SCREEN_WIDTH-1; - refreshArea.width = 0; - refreshArea.y0 = SCREEN_HEIGHT-1; - refreshArea.height = 0; - refreshArea.bpp = NBGL_BPP_2; +void nbgl_refreshReset(void) +{ + refreshArea.x0 = SCREEN_WIDTH - 1; + refreshArea.width = 0; + refreshArea.y0 = SCREEN_HEIGHT - 1; + refreshArea.height = 0; + refreshArea.bpp = NBGL_BPP_2; } /** * @brief This functions inits all internal of nbgl objects layer * */ -void nbgl_objInit(void) { - // init area to the smallest size - nbgl_refreshReset(); +void nbgl_objInit(void) +{ + // init area to the smallest size + nbgl_refreshReset(); } /** @@ -1236,6 +1399,7 @@ void nbgl_objInit(void) { * * @param enable if true, enables drawing/refresh, otherwise disables */ -void nbgl_objAllowDrawing(bool enable) { - objDrawingDisabled = !enable; +void nbgl_objAllowDrawing(bool enable) +{ + objDrawingDisabled = !enable; } diff --git a/lib_nbgl/src/nbgl_obj_keyboard.c b/lib_nbgl/src/nbgl_obj_keyboard.c index 3202b6558..82afb7660 100644 --- a/lib_nbgl/src/nbgl_obj_keyboard.c +++ b/lib_nbgl/src/nbgl_obj_keyboard.c @@ -23,27 +23,25 @@ * DEFINES *********************/ -#define FIRST_LINE_CHAR_COUNT 10 +#define FIRST_LINE_CHAR_COUNT 10 #define SECOND_LINE_CHAR_COUNT 9 -#define NORMAL_KEY_WIDTH 40 -#define LETTER_OFFSET_Y (((KEYBOARD_KEY_HEIGHT-32)/2)&0xFFC) -#define SHIFT_KEY_WIDTH (NORMAL_KEY_WIDTH+SECOND_LINE_OFFSET) -#define SECOND_LINE_OFFSET ((SCREEN_WIDTH-(SECOND_LINE_CHAR_COUNT*NORMAL_KEY_WIDTH))/2) -#define SPACE_KEY_WIDTH 276 -#define SWITCH_KEY_WIDTH (SCREEN_WIDTH-SPACE_KEY_WIDTH) -#define SPECIAL_CHARS_KEY_WIDTH (NORMAL_KEY_WIDTH*2+SECOND_LINE_OFFSET) -#define BACKSPACE_KEY_WIDTH_FULL SHIFT_KEY_WIDTH -#define BACKSPACE_KEY_WIDTH_DIGITS SPECIAL_CHARS_KEY_WIDTH -#define BACKSPACE_KEY_WIDTH_LETTERS_ONLY (SCREEN_WIDTH-7*NORMAL_KEY_WIDTH) - -#define SHIFT_KEY_INDEX 26 +#define NORMAL_KEY_WIDTH 40 +#define LETTER_OFFSET_Y (((KEYBOARD_KEY_HEIGHT - 32) / 2) & 0xFFC) +#define SHIFT_KEY_WIDTH (NORMAL_KEY_WIDTH + SECOND_LINE_OFFSET) +#define SECOND_LINE_OFFSET ((SCREEN_WIDTH - (SECOND_LINE_CHAR_COUNT * NORMAL_KEY_WIDTH)) / 2) +#define SPACE_KEY_WIDTH 276 +#define SWITCH_KEY_WIDTH (SCREEN_WIDTH - SPACE_KEY_WIDTH) +#define SPECIAL_CHARS_KEY_WIDTH (NORMAL_KEY_WIDTH * 2 + SECOND_LINE_OFFSET) +#define BACKSPACE_KEY_WIDTH_FULL SHIFT_KEY_WIDTH +#define BACKSPACE_KEY_WIDTH_DIGITS SPECIAL_CHARS_KEY_WIDTH +#define BACKSPACE_KEY_WIDTH_LETTERS_ONLY (SCREEN_WIDTH - 7 * NORMAL_KEY_WIDTH) + +#define SHIFT_KEY_INDEX 26 #define DIGITS_SWITCH_KEY_INDEX 27 -#define BACKSPACE_KEY_INDEX 28 -#define SPACE_KEY_INDEX 29 -#define SPECIAL_KEYS_INDEX 30 - - +#define BACKSPACE_KEY_INDEX 28 +#define SPACE_KEY_INDEX 29 +#define SPECIAL_KEYS_INDEX 30 /********************** * TYPEDEFS @@ -56,10 +54,10 @@ /********************** * STATIC VARIABLES **********************/ -static const char kbd_chars[] = "qwertyuiopasdfghjklzxcvbnm"; +static const char kbd_chars[] = "qwertyuiopasdfghjklzxcvbnm"; static const char kbd_chars_upper[] = "QWERTYUIOPASDFGHJKLZXCVBNM"; -const char kbd_digits[] = "1234567890-/:;()&@\".,?!\'"; -static const char kbd_specials[] = "[]{}#%^*+=_\\|~<>$`\".,?!\'"; +const char kbd_digits[] = "1234567890-/:;()&@\".,?!\'"; +static const char kbd_specials[] = "[]{}#%^*+=_\\|~<>$`\".,?!\'"; /********************** * VARIABLES @@ -68,391 +66,453 @@ static const char kbd_specials[] = "[]{}#%^*+=_\\|~<>$`\".,?!\'"; /********************** * STATIC FUNCTIONS **********************/ -static uint8_t getKeyboardIndex(nbgl_keyboard_t *keyboard, nbgl_touchStatePosition_t *position) { - uint8_t i=0; - // get index of key pressed - if (position->y < KEYBOARD_KEY_HEIGHT) { - // 1st row: - i = position->x/NORMAL_KEY_WIDTH; - } - else if (position->y < (2*KEYBOARD_KEY_HEIGHT)) { - // 2nd row: - i = FIRST_LINE_CHAR_COUNT + (position->x-SECOND_LINE_OFFSET)/NORMAL_KEY_WIDTH; - if (i >= FIRST_LINE_CHAR_COUNT + SECOND_LINE_CHAR_COUNT) { - i = FIRST_LINE_CHAR_COUNT + SECOND_LINE_CHAR_COUNT - 1; - } - } - else if (position->y < (3*KEYBOARD_KEY_HEIGHT)) { - // 3rd row: - if (keyboard->mode == MODE_LETTERS) { - // shift does not exist in letters only mode - if (!keyboard->lettersOnly) { - if (position->xy < KEYBOARD_KEY_HEIGHT) { + // 1st row: + i = position->x / NORMAL_KEY_WIDTH; + } + else if (position->y < (2 * KEYBOARD_KEY_HEIGHT)) { + // 2nd row: + i = FIRST_LINE_CHAR_COUNT + (position->x - SECOND_LINE_OFFSET) / NORMAL_KEY_WIDTH; + if (i >= FIRST_LINE_CHAR_COUNT + SECOND_LINE_CHAR_COUNT) { + i = FIRST_LINE_CHAR_COUNT + SECOND_LINE_CHAR_COUNT - 1; + } + } + else if (position->y < (3 * KEYBOARD_KEY_HEIGHT)) { + // 3rd row: + if (keyboard->mode == MODE_LETTERS) { + // shift does not exist in letters only mode + if (!keyboard->lettersOnly) { + if (position->x < SHIFT_KEY_WIDTH) { + i = SHIFT_KEY_INDEX; + } + else { + i = FIRST_LINE_CHAR_COUNT + SECOND_LINE_CHAR_COUNT + + (position->x - SHIFT_KEY_WIDTH) / NORMAL_KEY_WIDTH; + // Backspace key is a bit larger... + if (i >= 26) { + i = BACKSPACE_KEY_INDEX; + } + } + } + else { + i = FIRST_LINE_CHAR_COUNT + SECOND_LINE_CHAR_COUNT + position->x / NORMAL_KEY_WIDTH; + // Backspace key is larger... + if (i >= 26) { + i = BACKSPACE_KEY_INDEX; + } + } } else { - i = FIRST_LINE_CHAR_COUNT + SECOND_LINE_CHAR_COUNT + (position->x-SHIFT_KEY_WIDTH)/NORMAL_KEY_WIDTH; - // Backspace key is a bit larger... - if (i>=26) - i = BACKSPACE_KEY_INDEX; + if (position->x < SPECIAL_CHARS_KEY_WIDTH) { + i = SPECIAL_KEYS_INDEX; + } + else { + i = FIRST_LINE_CHAR_COUNT + SECOND_LINE_CHAR_COUNT + + (position->x - SPECIAL_CHARS_KEY_WIDTH) / NORMAL_KEY_WIDTH; + // Backspace key is a bit larger... + if (i >= 24) { + i = BACKSPACE_KEY_INDEX; + } + } } - } - else { - i = FIRST_LINE_CHAR_COUNT + SECOND_LINE_CHAR_COUNT + position->x/NORMAL_KEY_WIDTH; - // Backspace key is larger... - if (i>=26) - i = BACKSPACE_KEY_INDEX; - } } - else { - if (position->xx-SPECIAL_CHARS_KEY_WIDTH)/NORMAL_KEY_WIDTH; - // Backspace key is a bit larger... - if (i>=24) - i = BACKSPACE_KEY_INDEX; - } - } - } - else if (!keyboard->lettersOnly && (position->y < (4*KEYBOARD_KEY_HEIGHT))) { - // 4th row - if (position->xlettersOnly && (position->y < (4 * KEYBOARD_KEY_HEIGHT))) { + // 4th row + if (position->x < SWITCH_KEY_WIDTH) { + i = DIGITS_SWITCH_KEY_INDEX; + } + else { + i = SPACE_KEY_INDEX; + } } - } - return i; + return i; } // draw parts common to all modes of keyboard -static void keyboardDrawCommonLines(nbgl_keyboard_t *keyboard) { - nbgl_area_t rectArea; - - // clean full area - rectArea.backgroundColor = keyboard->obj.area.backgroundColor; - rectArea.x0 = keyboard->obj.area.x0; - rectArea.y0 = keyboard->obj.area.y0; - rectArea.width = keyboard->obj.area.width; - rectArea.height = keyboard->obj.area.height; - nbgl_frontDrawRect(&rectArea); - - /// draw horizontal lines - rectArea.backgroundColor = keyboard->obj.area.backgroundColor; - rectArea.x0 = keyboard->obj.area.x0; - rectArea.y0 = keyboard->obj.area.y0; - rectArea.width = keyboard->obj.area.width; - rectArea.height = 4; - nbgl_frontDrawHorizontalLine(&rectArea, 0x1, keyboard->borderColor); // 1st line (top) - rectArea.y0 += KEYBOARD_KEY_HEIGHT; - nbgl_frontDrawHorizontalLine(&rectArea, 0x1, keyboard->borderColor); // 2nd line - rectArea.y0 += KEYBOARD_KEY_HEIGHT; - nbgl_frontDrawHorizontalLine(&rectArea, 0x1, keyboard->borderColor); // 3rd line - rectArea.y0 += KEYBOARD_KEY_HEIGHT; - nbgl_frontDrawHorizontalLine(&rectArea, 0x1, keyboard->borderColor); // 4th line - if (!keyboard->lettersOnly) { - rectArea.y0 += KEYBOARD_KEY_HEIGHT; - nbgl_frontDrawHorizontalLine(&rectArea, 0x1, keyboard->borderColor); // 5th line - } - /// then draw vertical lines - rectArea.backgroundColor = keyboard->borderColor; - rectArea.x0 = keyboard->obj.area.x0; - rectArea.y0 = keyboard->obj.area.y0; - rectArea.width = 1; - rectArea.height = KEYBOARD_KEY_HEIGHT*3; - if (!keyboard->lettersOnly) - rectArea.height += KEYBOARD_KEY_HEIGHT; - nbgl_frontDrawRect(&rectArea); // 1st full line, on the left +static void keyboardDrawCommonLines(nbgl_keyboard_t *keyboard) +{ + nbgl_area_t rectArea; + + // clean full area + rectArea.backgroundColor = keyboard->obj.area.backgroundColor; + rectArea.x0 = keyboard->obj.area.x0; + rectArea.y0 = keyboard->obj.area.y0; + rectArea.width = keyboard->obj.area.width; + rectArea.height = keyboard->obj.area.height; + nbgl_frontDrawRect(&rectArea); + /// draw horizontal lines + rectArea.backgroundColor = keyboard->obj.area.backgroundColor; + rectArea.x0 = keyboard->obj.area.x0; + rectArea.y0 = keyboard->obj.area.y0; + rectArea.width = keyboard->obj.area.width; + rectArea.height = 4; + nbgl_frontDrawHorizontalLine(&rectArea, 0x1, keyboard->borderColor); // 1st line (top) + rectArea.y0 += KEYBOARD_KEY_HEIGHT; + nbgl_frontDrawHorizontalLine(&rectArea, 0x1, keyboard->borderColor); // 2nd line + rectArea.y0 += KEYBOARD_KEY_HEIGHT; + nbgl_frontDrawHorizontalLine(&rectArea, 0x1, keyboard->borderColor); // 3rd line + rectArea.y0 += KEYBOARD_KEY_HEIGHT; + nbgl_frontDrawHorizontalLine(&rectArea, 0x1, keyboard->borderColor); // 4th line + if (!keyboard->lettersOnly) { + rectArea.y0 += KEYBOARD_KEY_HEIGHT; + nbgl_frontDrawHorizontalLine(&rectArea, 0x1, keyboard->borderColor); // 5th line + } + /// then draw vertical lines + rectArea.backgroundColor = keyboard->borderColor; + rectArea.x0 = keyboard->obj.area.x0; + rectArea.y0 = keyboard->obj.area.y0; + rectArea.width = 1; + rectArea.height = KEYBOARD_KEY_HEIGHT * 3; + if (!keyboard->lettersOnly) { + rectArea.height += KEYBOARD_KEY_HEIGHT; + } + nbgl_frontDrawRect(&rectArea); // 1st full line, on the left } // draw full grid for letters mode -static void keyboardDrawLetterGrid(nbgl_keyboard_t *keyboard) { - nbgl_area_t rectArea; - uint8_t i; - - /// draw common lines - keyboardDrawCommonLines(keyboard); - - // then all vertical lines separating keys - rectArea.backgroundColor = keyboard->borderColor; - rectArea.x0 = keyboard->obj.area.x0; - rectArea.y0 = keyboard->obj.area.y0; - rectArea.width = 1; - rectArea.height = KEYBOARD_KEY_HEIGHT; - // First row of keys: 10 letters (qwertyuiop) - for (i=0;i<9;i++) { - rectArea.x0 += NORMAL_KEY_WIDTH; - nbgl_frontDrawRect(&rectArea); - } - - // Second row: 9 letters (asdfghjkl) - rectArea.x0 = keyboard->obj.area.x0+SECOND_LINE_OFFSET; - rectArea.y0 += KEYBOARD_KEY_HEIGHT; - nbgl_frontDrawRect(&rectArea); - for (i=10;i<19;i++) { - rectArea.x0 += NORMAL_KEY_WIDTH; - nbgl_frontDrawRect(&rectArea); - } - // Third row: Shift key, 7 letters (zxcvbnm) and backspace in normal mode - // Third row: 7 letters (zxcvbnm) and backspace in letters only mode - rectArea.y0 += KEYBOARD_KEY_HEIGHT; - if (!keyboard->lettersOnly) { - rectArea.x0 = keyboard->obj.area.x0+SHIFT_KEY_WIDTH; - } - else { - rectArea.x0 = NORMAL_KEY_WIDTH; - } - for (i=0;i<6;i++) { - nbgl_frontDrawRect(&rectArea); - rectArea.x0 += NORMAL_KEY_WIDTH; - } - if (!keyboard->lettersOnly) { - nbgl_frontDrawRect(&rectArea); - rectArea.x0 += NORMAL_KEY_WIDTH; - } - nbgl_frontDrawRect(&rectArea); +static void keyboardDrawLetterGrid(nbgl_keyboard_t *keyboard) +{ + nbgl_area_t rectArea; + uint8_t i; + + /// draw common lines + keyboardDrawCommonLines(keyboard); + + // then all vertical lines separating keys + rectArea.backgroundColor = keyboard->borderColor; + rectArea.x0 = keyboard->obj.area.x0; + rectArea.y0 = keyboard->obj.area.y0; + rectArea.width = 1; + rectArea.height = KEYBOARD_KEY_HEIGHT; + // First row of keys: 10 letters (qwertyuiop) + for (i = 0; i < 9; i++) { + rectArea.x0 += NORMAL_KEY_WIDTH; + nbgl_frontDrawRect(&rectArea); + } - // 4th row, only in Full mode - if (!keyboard->lettersOnly) { + // Second row: 9 letters (asdfghjkl) + rectArea.x0 = keyboard->obj.area.x0 + SECOND_LINE_OFFSET; rectArea.y0 += KEYBOARD_KEY_HEIGHT; - rectArea.x0 = keyboard->obj.area.x0+SWITCH_KEY_WIDTH; nbgl_frontDrawRect(&rectArea); - } + for (i = 10; i < 19; i++) { + rectArea.x0 += NORMAL_KEY_WIDTH; + nbgl_frontDrawRect(&rectArea); + } + // Third row: Shift key, 7 letters (zxcvbnm) and backspace in normal mode + // Third row: 7 letters (zxcvbnm) and backspace in letters only mode + rectArea.y0 += KEYBOARD_KEY_HEIGHT; + if (!keyboard->lettersOnly) { + rectArea.x0 = keyboard->obj.area.x0 + SHIFT_KEY_WIDTH; + } + else { + rectArea.x0 = NORMAL_KEY_WIDTH; + } + for (i = 0; i < 6; i++) { + nbgl_frontDrawRect(&rectArea); + rectArea.x0 += NORMAL_KEY_WIDTH; + } + if (!keyboard->lettersOnly) { + nbgl_frontDrawRect(&rectArea); + rectArea.x0 += NORMAL_KEY_WIDTH; + } + nbgl_frontDrawRect(&rectArea); + + // 4th row, only in Full mode + if (!keyboard->lettersOnly) { + rectArea.y0 += KEYBOARD_KEY_HEIGHT; + rectArea.x0 = keyboard->obj.area.x0 + SWITCH_KEY_WIDTH; + nbgl_frontDrawRect(&rectArea); + } } // draw full grid for digits/special mode -static void keyboardDrawDigitsGrid(nbgl_keyboard_t *keyboard) { - nbgl_area_t rectArea; - uint8_t i; - - /// draw common lines - keyboardDrawCommonLines(keyboard); - - // then all vertical lines separating keys - rectArea.backgroundColor = keyboard->borderColor; - rectArea.x0 = keyboard->obj.area.x0; - rectArea.y0 = keyboard->obj.area.y0; - rectArea.width = 1; - rectArea.height = KEYBOARD_KEY_HEIGHT; - // First row of keys: 10 keys so 9 separations - for (i=0;i<9;i++) { - rectArea.x0 += NORMAL_KEY_WIDTH; - nbgl_frontDrawRect(&rectArea); - } - - // Second row: 9 keys - rectArea.x0 = keyboard->obj.area.x0+SECOND_LINE_OFFSET; - rectArea.y0 += KEYBOARD_KEY_HEIGHT; - nbgl_frontDrawRect(&rectArea); - for (i=10;i<19;i++) { - rectArea.x0 += NORMAL_KEY_WIDTH; +static void keyboardDrawDigitsGrid(nbgl_keyboard_t *keyboard) +{ + nbgl_area_t rectArea; + uint8_t i; + + /// draw common lines + keyboardDrawCommonLines(keyboard); + + // then all vertical lines separating keys + rectArea.backgroundColor = keyboard->borderColor; + rectArea.x0 = keyboard->obj.area.x0; + rectArea.y0 = keyboard->obj.area.y0; + rectArea.width = 1; + rectArea.height = KEYBOARD_KEY_HEIGHT; + // First row of keys: 10 keys so 9 separations + for (i = 0; i < 9; i++) { + rectArea.x0 += NORMAL_KEY_WIDTH; + nbgl_frontDrawRect(&rectArea); + } + + // Second row: 9 keys + rectArea.x0 = keyboard->obj.area.x0 + SECOND_LINE_OFFSET; + rectArea.y0 += KEYBOARD_KEY_HEIGHT; nbgl_frontDrawRect(&rectArea); - } - // Third row: Special char key, 5 keys and backspace - rectArea.x0 = keyboard->obj.area.x0+SPECIAL_CHARS_KEY_WIDTH; - rectArea.y0 += KEYBOARD_KEY_HEIGHT; - nbgl_frontDrawRect(&rectArea); - for (i=0;i<5;i++) { - rectArea.x0 += NORMAL_KEY_WIDTH; + for (i = 10; i < 19; i++) { + rectArea.x0 += NORMAL_KEY_WIDTH; + nbgl_frontDrawRect(&rectArea); + } + // Third row: Special char key, 5 keys and backspace + rectArea.x0 = keyboard->obj.area.x0 + SPECIAL_CHARS_KEY_WIDTH; + rectArea.y0 += KEYBOARD_KEY_HEIGHT; nbgl_frontDrawRect(&rectArea); - } + for (i = 0; i < 5; i++) { + rectArea.x0 += NORMAL_KEY_WIDTH; + nbgl_frontDrawRect(&rectArea); + } - // 4th row, switch to letters and space - rectArea.y0 += KEYBOARD_KEY_HEIGHT; - rectArea.x0 = keyboard->obj.area.x0+SWITCH_KEY_WIDTH; - nbgl_frontDrawRect(&rectArea); + // 4th row, switch to letters and space + rectArea.y0 += KEYBOARD_KEY_HEIGHT; + rectArea.x0 = keyboard->obj.area.x0 + SWITCH_KEY_WIDTH; + nbgl_frontDrawRect(&rectArea); } // draw letters for letters mode -static void keyboardDrawLetters(nbgl_keyboard_t *keyboard) { - uint8_t i; - nbgl_area_t rectArea; - const char *keys; - - if (keyboard->casing != LOWER_CASE) - keys = kbd_chars_upper; - else - keys = kbd_chars; - - rectArea.backgroundColor = keyboard->obj.area.backgroundColor; - rectArea.y0 = keyboard->obj.area.y0 + LETTER_OFFSET_Y; - rectArea.width = 1; - rectArea.height = KEYBOARD_KEY_HEIGHT*3; - rectArea.x0 = keyboard->obj.area.x0; - - // First row of keys: 10 letters (qwertyuiop) - for (i=0;i<10;i++) { - rectArea.x0 = keyboard->obj.area.x0 + i*NORMAL_KEY_WIDTH; - - rectArea.x0 += (NORMAL_KEY_WIDTH-nbgl_getCharWidth(BAGL_FONT_INTER_REGULAR_24px_1bpp,&keys[i]))/2; - nbgl_drawText(&rectArea, &keys[i], - 1, BAGL_FONT_INTER_REGULAR_24px_1bpp, - (keyboard->keyMask&(1<obj.area.x0 + SECOND_LINE_OFFSET + (i-10)*NORMAL_KEY_WIDTH; - rectArea.x0 += (NORMAL_KEY_WIDTH-nbgl_getCharWidth(BAGL_FONT_INTER_REGULAR_24px_1bpp,&keys[i]))/2; - nbgl_drawText(&rectArea, &keys[i], - 1, BAGL_FONT_INTER_REGULAR_24px_1bpp, - (keyboard->keyMask&(1<lettersOnly) { - // draw background rectangle - rectArea.width = SHIFT_KEY_WIDTH-1; - rectArea.height = KEYBOARD_KEY_HEIGHT; - rectArea.bpp = NBGL_BPP_1; - rectArea.y0 = keyboard->obj.area.y0 + KEYBOARD_KEY_HEIGHT*2; - rectArea.x0 = 1; - rectArea.backgroundColor = (keyboard->casing != LOWER_CASE)?BLACK:WHITE; - nbgl_frontDrawRect(&rectArea); - //draw horizontal line - rectArea.width = SHIFT_KEY_WIDTH-1; - rectArea.height = 4; - rectArea.x0 = 1; - rectArea.y0 = keyboard->obj.area.y0 + KEYBOARD_KEY_HEIGHT*2; - rectArea.backgroundColor = (keyboard->casing != LOWER_CASE)?BLACK:WHITE; - nbgl_frontDrawHorizontalLine(&rectArea, 0x1, keyboard->borderColor); - // draw Shift key - rectArea.width = C_shift32px.width; - rectArea.height = C_shift32px.height; - rectArea.bpp = NBGL_BPP_1; - rectArea.y0 = (keyboard->obj.area.y0 + KEYBOARD_KEY_HEIGHT*2 + (KEYBOARD_KEY_HEIGHT-rectArea.height)/2) & 0xFFC; - rectArea.x0 = (SHIFT_KEY_WIDTH-rectArea.width)/2; - rectArea.backgroundColor = (keyboard->casing != LOWER_CASE)?BLACK:WHITE; - nbgl_drawIcon(&rectArea, - (keyboard->casing != LOWER_CASE)?WHITE:BLACK, - (keyboard->casing != LOCKED_UPPER_CASE)?(&C_shift_lock32px):(&C_shift32px)); - rectArea.backgroundColor = WHITE; - offsetX = keyboard->obj.area.x0 + SHIFT_KEY_WIDTH; - } - else { - offsetX = 0; - } - rectArea.y0 = keyboard->obj.area.y0 + KEYBOARD_KEY_HEIGHT*2 + LETTER_OFFSET_Y; - for (i=19;i<26;i++) { - rectArea.x0 = offsetX + (i-19)*NORMAL_KEY_WIDTH; - rectArea.x0 += (NORMAL_KEY_WIDTH-nbgl_getCharWidth(BAGL_FONT_INTER_REGULAR_24px_1bpp,&keys[i]))/2; - nbgl_drawText(&rectArea, &keys[i], - 1, BAGL_FONT_INTER_REGULAR_24px_1bpp, - (keyboard->keyMask&(1<obj.area.y0 + KEYBOARD_KEY_HEIGHT*2 + (KEYBOARD_KEY_HEIGHT-rectArea.height)/2) & 0xFFC; - if (!keyboard->lettersOnly) { - rectArea.x0 += (BACKSPACE_KEY_WIDTH_FULL-rectArea.width)/2; - } - else { - rectArea.x0 += (BACKSPACE_KEY_WIDTH_LETTERS_ONLY-rectArea.width)/2; - } - nbgl_drawIcon(&rectArea, BLACK, &C_backspace32px); - - // 4th row, only in Full mode - if (!keyboard->lettersOnly) { - rectArea.x0 = (SWITCH_KEY_WIDTH-nbgl_getTextWidth(BAGL_FONT_INTER_REGULAR_24px_1bpp,".?123"))/2; - rectArea.y0 = keyboard->obj.area.y0 + KEYBOARD_KEY_HEIGHT*3 + LETTER_OFFSET_Y; - nbgl_drawText(&rectArea, ".?123", 5, BAGL_FONT_INTER_REGULAR_24px_1bpp, BLACK); - - rectArea.x0 = SWITCH_KEY_WIDTH+(SPACE_KEY_WIDTH-C_space32px.width)/2; - nbgl_drawIcon(&rectArea, (keyboard->keyMask&(1<casing != LOWER_CASE) { + keys = kbd_chars_upper; + } + else { + keys = kbd_chars; + } + rectArea.backgroundColor = keyboard->obj.area.backgroundColor; + rectArea.y0 = keyboard->obj.area.y0 + LETTER_OFFSET_Y; + rectArea.width = 1; + rectArea.height = KEYBOARD_KEY_HEIGHT * 3; + rectArea.x0 = keyboard->obj.area.x0; + + // First row of keys: 10 letters (qwertyuiop) + for (i = 0; i < 10; i++) { + rectArea.x0 = keyboard->obj.area.x0 + i * NORMAL_KEY_WIDTH; + + rectArea.x0 + += (NORMAL_KEY_WIDTH - nbgl_getCharWidth(BAGL_FONT_INTER_REGULAR_24px_1bpp, &keys[i])) + / 2; + nbgl_drawText(&rectArea, + &keys[i], + 1, + BAGL_FONT_INTER_REGULAR_24px_1bpp, + (keyboard->keyMask & (1 << i)) ? WHITE : BLACK); + } + // Second row: 9 letters (asdfghjkl) + rectArea.y0 += KEYBOARD_KEY_HEIGHT; + for (i = 10; i < 19; i++) { + rectArea.x0 = keyboard->obj.area.x0 + SECOND_LINE_OFFSET + (i - 10) * NORMAL_KEY_WIDTH; + rectArea.x0 + += (NORMAL_KEY_WIDTH - nbgl_getCharWidth(BAGL_FONT_INTER_REGULAR_24px_1bpp, &keys[i])) + / 2; + nbgl_drawText(&rectArea, + &keys[i], + 1, + BAGL_FONT_INTER_REGULAR_24px_1bpp, + (keyboard->keyMask & (1 << i)) ? WHITE : BLACK); + } + // Third row: Shift key, 7 letters (zxcvbnm) and backspace + rectArea.y0 += KEYBOARD_KEY_HEIGHT; + uint16_t offsetX; + if (!keyboard->lettersOnly) { + // draw background rectangle + rectArea.width = SHIFT_KEY_WIDTH - 1; + rectArea.height = KEYBOARD_KEY_HEIGHT; + rectArea.bpp = NBGL_BPP_1; + rectArea.y0 = keyboard->obj.area.y0 + KEYBOARD_KEY_HEIGHT * 2; + rectArea.x0 = 1; + rectArea.backgroundColor = (keyboard->casing != LOWER_CASE) ? BLACK : WHITE; + nbgl_frontDrawRect(&rectArea); + // draw horizontal line + rectArea.width = SHIFT_KEY_WIDTH - 1; + rectArea.height = 4; + rectArea.x0 = 1; + rectArea.y0 = keyboard->obj.area.y0 + KEYBOARD_KEY_HEIGHT * 2; + rectArea.backgroundColor = (keyboard->casing != LOWER_CASE) ? BLACK : WHITE; + nbgl_frontDrawHorizontalLine(&rectArea, 0x1, keyboard->borderColor); + // draw Shift key + rectArea.width = C_shift32px.width; + rectArea.height = C_shift32px.height; + rectArea.bpp = NBGL_BPP_1; + rectArea.y0 = (keyboard->obj.area.y0 + KEYBOARD_KEY_HEIGHT * 2 + + (KEYBOARD_KEY_HEIGHT - rectArea.height) / 2) + & 0xFFC; + rectArea.x0 = (SHIFT_KEY_WIDTH - rectArea.width) / 2; + rectArea.backgroundColor = (keyboard->casing != LOWER_CASE) ? BLACK : WHITE; + nbgl_drawIcon( + &rectArea, + (keyboard->casing != LOWER_CASE) ? WHITE : BLACK, + (keyboard->casing != LOCKED_UPPER_CASE) ? (&C_shift_lock32px) : (&C_shift32px)); + rectArea.backgroundColor = WHITE; + offsetX = keyboard->obj.area.x0 + SHIFT_KEY_WIDTH; + } + else { + offsetX = 0; + } + rectArea.y0 = keyboard->obj.area.y0 + KEYBOARD_KEY_HEIGHT * 2 + LETTER_OFFSET_Y; + for (i = 19; i < 26; i++) { + rectArea.x0 = offsetX + (i - 19) * NORMAL_KEY_WIDTH; + rectArea.x0 + += (NORMAL_KEY_WIDTH - nbgl_getCharWidth(BAGL_FONT_INTER_REGULAR_24px_1bpp, &keys[i])) + / 2; + nbgl_drawText(&rectArea, + &keys[i], + 1, + BAGL_FONT_INTER_REGULAR_24px_1bpp, + (keyboard->keyMask & (1 << i)) ? WHITE : BLACK); + } + // draw backspace + rectArea.width = C_backspace32px.width; + rectArea.height = C_backspace32px.height; + rectArea.bpp = NBGL_BPP_1; + rectArea.x0 = offsetX + 7 * NORMAL_KEY_WIDTH; + rectArea.y0 = (keyboard->obj.area.y0 + KEYBOARD_KEY_HEIGHT * 2 + + (KEYBOARD_KEY_HEIGHT - rectArea.height) / 2) + & 0xFFC; + if (!keyboard->lettersOnly) { + rectArea.x0 += (BACKSPACE_KEY_WIDTH_FULL - rectArea.width) / 2; + } + else { + rectArea.x0 += (BACKSPACE_KEY_WIDTH_LETTERS_ONLY - rectArea.width) / 2; + } + nbgl_drawIcon(&rectArea, BLACK, &C_backspace32px); + + // 4th row, only in Full mode + if (!keyboard->lettersOnly) { + rectArea.x0 + = (SWITCH_KEY_WIDTH - nbgl_getTextWidth(BAGL_FONT_INTER_REGULAR_24px_1bpp, ".?123")) + / 2; + rectArea.y0 = keyboard->obj.area.y0 + KEYBOARD_KEY_HEIGHT * 3 + LETTER_OFFSET_Y; + nbgl_drawText(&rectArea, ".?123", 5, BAGL_FONT_INTER_REGULAR_24px_1bpp, BLACK); + + rectArea.x0 = SWITCH_KEY_WIDTH + (SPACE_KEY_WIDTH - C_space32px.width) / 2; + nbgl_drawIcon( + &rectArea, (keyboard->keyMask & (1 << SPACE_KEY_INDEX)) ? WHITE : BLACK, &C_space32px); + } } // draw digits/special chars for digits/special mode -static void keyboardDrawDigits(nbgl_keyboard_t *keyboard) { - uint8_t i; - nbgl_area_t rectArea; - const char *keys; - - if (keyboard->mode == MODE_DIGITS) - keys = kbd_digits; - else - keys = kbd_specials; - - rectArea.backgroundColor = keyboard->obj.area.backgroundColor; - rectArea.y0 = keyboard->obj.area.y0 + LETTER_OFFSET_Y; - rectArea.width = 1; - rectArea.height = KEYBOARD_KEY_HEIGHT*3; - rectArea.x0 = keyboard->obj.area.x0; - - // First row of keys: 10 digits (1234567890) - for (i=0;i<10;i++) { - rectArea.x0 = keyboard->obj.area.x0 + i*NORMAL_KEY_WIDTH; - rectArea.x0 += (NORMAL_KEY_WIDTH-nbgl_getCharWidth(BAGL_FONT_INTER_REGULAR_24px_1bpp,&keys[i]))/2; - nbgl_drawText(&rectArea, &keys[i], 1, BAGL_FONT_INTER_REGULAR_24px_1bpp, (keyboard->keyMask&(1<obj.area.x0 + (i-10)*NORMAL_KEY_WIDTH + SECOND_LINE_OFFSET; - rectArea.x0 += (NORMAL_KEY_WIDTH-nbgl_getCharWidth(BAGL_FONT_INTER_REGULAR_24px_1bpp,&keys[i]))/2; - nbgl_drawText(&rectArea, &keys[i], 1, BAGL_FONT_INTER_REGULAR_24px_1bpp, (keyboard->keyMask&(1<obj.area.y0 + KEYBOARD_KEY_HEIGHT*2 + LETTER_OFFSET_Y; - nbgl_drawText(&rectArea, "123", 3, BAGL_FONT_INTER_REGULAR_24px_1bpp, BLACK); - } - - for (i=19;i<24;i++) { - rectArea.x0 = SPECIAL_CHARS_KEY_WIDTH + (i-19)*NORMAL_KEY_WIDTH; - rectArea.x0 += (NORMAL_KEY_WIDTH-nbgl_getCharWidth(BAGL_FONT_INTER_REGULAR_24px_1bpp,&keys[i]))/2; - nbgl_drawText(&rectArea, &keys[i], 1, BAGL_FONT_INTER_REGULAR_24px_1bpp, (keyboard->keyMask&(1<obj.area.y0 + KEYBOARD_KEY_HEIGHT*2 + (KEYBOARD_KEY_HEIGHT-rectArea.height)/2; - rectArea.x0 += (BACKSPACE_KEY_WIDTH_DIGITS-rectArea.width)/2; - nbgl_frontDrawImage(&rectArea,(uint8_t*)C_backspace32px.bitmap,NO_TRANSFORMATION,BLACK); - - // 4th row - rectArea.x0 = (SWITCH_KEY_WIDTH-nbgl_getTextWidth(BAGL_FONT_INTER_REGULAR_24px_1bpp,"ABC"))/2; - rectArea.y0 = keyboard->obj.area.y0 + KEYBOARD_KEY_HEIGHT*3 + LETTER_OFFSET_Y; - nbgl_drawText(&rectArea, "ABC", 3, BAGL_FONT_INTER_REGULAR_24px_1bpp, BLACK); - - rectArea.x0 = SWITCH_KEY_WIDTH+(SPACE_KEY_WIDTH-C_space32px.width)/2; - nbgl_frontDrawImage(&rectArea,(uint8_t*)C_space32px.bitmap, NO_TRANSFORMATION, (keyboard->keyMask&(1<mode == MODE_DIGITS) { + keys = kbd_digits; + } + else { + keys = kbd_specials; + } + + rectArea.backgroundColor = keyboard->obj.area.backgroundColor; + rectArea.y0 = keyboard->obj.area.y0 + LETTER_OFFSET_Y; + rectArea.width = 1; + rectArea.height = KEYBOARD_KEY_HEIGHT * 3; + rectArea.x0 = keyboard->obj.area.x0; + + // First row of keys: 10 digits (1234567890) + for (i = 0; i < 10; i++) { + rectArea.x0 = keyboard->obj.area.x0 + i * NORMAL_KEY_WIDTH; + rectArea.x0 + += (NORMAL_KEY_WIDTH - nbgl_getCharWidth(BAGL_FONT_INTER_REGULAR_24px_1bpp, &keys[i])) + / 2; + nbgl_drawText(&rectArea, + &keys[i], + 1, + BAGL_FONT_INTER_REGULAR_24px_1bpp, + (keyboard->keyMask & (1 << i)) ? WHITE : BLACK); + } + // Second row: 9 keys () + rectArea.y0 += KEYBOARD_KEY_HEIGHT; + for (i = 10; i < 19; i++) { + rectArea.x0 = keyboard->obj.area.x0 + (i - 10) * NORMAL_KEY_WIDTH + SECOND_LINE_OFFSET; + rectArea.x0 + += (NORMAL_KEY_WIDTH - nbgl_getCharWidth(BAGL_FONT_INTER_REGULAR_24px_1bpp, &keys[i])) + / 2; + nbgl_drawText(&rectArea, + &keys[i], + 1, + BAGL_FONT_INTER_REGULAR_24px_1bpp, + (keyboard->keyMask & (1 << i)) ? WHITE : BLACK); + } + // Third row: special key, 5 keys and backspace + + // draw "#+=" key + if (keyboard->mode == MODE_DIGITS) { + rectArea.x0 = (SPECIAL_CHARS_KEY_WIDTH + - nbgl_getTextWidth(BAGL_FONT_INTER_REGULAR_24px_1bpp, "#+=")) + / 2; + rectArea.y0 = keyboard->obj.area.y0 + KEYBOARD_KEY_HEIGHT * 2 + LETTER_OFFSET_Y; + nbgl_drawText(&rectArea, "#+=", 3, BAGL_FONT_INTER_REGULAR_24px_1bpp, BLACK); + } + else { + rectArea.x0 = (SPECIAL_CHARS_KEY_WIDTH + - nbgl_getTextWidth(BAGL_FONT_INTER_REGULAR_24px_1bpp, "123")) + / 2; + rectArea.y0 = keyboard->obj.area.y0 + KEYBOARD_KEY_HEIGHT * 2 + LETTER_OFFSET_Y; + nbgl_drawText(&rectArea, "123", 3, BAGL_FONT_INTER_REGULAR_24px_1bpp, BLACK); + } + + for (i = 19; i < 24; i++) { + rectArea.x0 = SPECIAL_CHARS_KEY_WIDTH + (i - 19) * NORMAL_KEY_WIDTH; + rectArea.x0 + += (NORMAL_KEY_WIDTH - nbgl_getCharWidth(BAGL_FONT_INTER_REGULAR_24px_1bpp, &keys[i])) + / 2; + nbgl_drawText(&rectArea, + &keys[i], + 1, + BAGL_FONT_INTER_REGULAR_24px_1bpp, + (keyboard->keyMask & (1 << i)) ? WHITE : BLACK); + } + // draw backspace + rectArea.width = C_backspace32px.width; + rectArea.height = C_backspace32px.height; + rectArea.bpp = NBGL_BPP_1; + rectArea.x0 = SPECIAL_CHARS_KEY_WIDTH + 5 * NORMAL_KEY_WIDTH; + rectArea.y0 = keyboard->obj.area.y0 + KEYBOARD_KEY_HEIGHT * 2 + + (KEYBOARD_KEY_HEIGHT - rectArea.height) / 2; + rectArea.x0 += (BACKSPACE_KEY_WIDTH_DIGITS - rectArea.width) / 2; + nbgl_frontDrawImage(&rectArea, (uint8_t *) C_backspace32px.bitmap, NO_TRANSFORMATION, BLACK); + + // 4th row + rectArea.x0 + = (SWITCH_KEY_WIDTH - nbgl_getTextWidth(BAGL_FONT_INTER_REGULAR_24px_1bpp, "ABC")) / 2; + rectArea.y0 = keyboard->obj.area.y0 + KEYBOARD_KEY_HEIGHT * 3 + LETTER_OFFSET_Y; + nbgl_drawText(&rectArea, "ABC", 3, BAGL_FONT_INTER_REGULAR_24px_1bpp, BLACK); + + rectArea.x0 = SWITCH_KEY_WIDTH + (SPACE_KEY_WIDTH - C_space32px.width) / 2; + nbgl_frontDrawImage(&rectArea, + (uint8_t *) C_space32px.bitmap, + NO_TRANSFORMATION, + (keyboard->keyMask & (1 << SPACE_KEY_INDEX)) ? WHITE : BLACK); } -static void keyboardDraw(nbgl_keyboard_t *keyboard) { - if (keyboard->mode == MODE_LETTERS) { - // At first, draw grid - keyboardDrawLetterGrid(keyboard); - - // then draw key content - keyboardDrawLetters(keyboard); - } - else { - ////// At first, draw grid ////// - keyboardDrawDigitsGrid(keyboard); - - ////// then draw key content ////// - keyboardDrawDigits(keyboard); - } +static void keyboardDraw(nbgl_keyboard_t *keyboard) +{ + if (keyboard->mode == MODE_LETTERS) { + // At first, draw grid + keyboardDrawLetterGrid(keyboard); + + // then draw key content + keyboardDrawLetters(keyboard); + } + else { + ////// At first, draw grid ////// + keyboardDrawDigitsGrid(keyboard); + + ////// then draw key content ////// + keyboardDrawDigits(keyboard); + } } /********************** @@ -466,103 +526,115 @@ static void keyboardDraw(nbgl_keyboard_t *keyboard) { * @param eventType type of touch (only TOUCHED is accepted) * @return none */ -void nbgl_keyboardTouchCallback(nbgl_obj_t *obj, nbgl_touchType_t eventType) { - uint8_t firstIndex, lastIndex; - nbgl_touchStatePosition_t *firstPosition, *lastPosition; - nbgl_keyboard_t *keyboard = (nbgl_keyboard_t *)obj; - - LOG_DEBUG(MISC_LOGGER,"keyboardTouchCallback(): eventType = %d\n",eventType); - if (eventType != TOUCHED) { - return; - } - if (nbgl_touchGetTouchedPosition(obj,&firstPosition,&lastPosition) == false) { - return; - } - // modify positions with keyboard position - firstPosition->x -= obj->area.x0; - firstPosition->y -= obj->area.y0; - lastPosition->x -= obj->area.x0; - lastPosition->y -= obj->area.y0; - - firstIndex = getKeyboardIndex(keyboard,firstPosition); - if (firstIndex > SPECIAL_KEYS_INDEX) - return; - lastIndex = getKeyboardIndex(keyboard,lastPosition); - if (lastIndex > SPECIAL_KEYS_INDEX) - return; - // if position of finger has moved durinng press to another "key", drop it - if (lastIndex != firstIndex) - return; - - if (keyboard->mode == MODE_LETTERS) { - keyboardCase_t cur_casing = keyboard->casing; - // if the casing mode was upper (not-locked), go back to lower case - if ((keyboard->casing == UPPER_CASE)&&(firstIndex != SHIFT_KEY_INDEX)) { - keyboard->casing = LOWER_CASE; - // just redraw, refresh will be done by client (user of keyboard) - nbgl_redrawObject((nbgl_obj_t *)keyboard,NULL,false); - keyboard->needsRefresh = true; - } - if ((firstIndex<26)&&((keyboard->keyMask&(1<callback((cur_casing != LOWER_CASE)?kbd_chars_upper[firstIndex]:kbd_chars[firstIndex]); - } - else if (firstIndex==SHIFT_KEY_INDEX) { - switch (keyboard->casing) { - case LOWER_CASE: - keyboard->casing = UPPER_CASE; - break; - case UPPER_CASE: - keyboard->casing = LOCKED_UPPER_CASE; - break; - case LOCKED_UPPER_CASE: - keyboard->casing = LOWER_CASE; - break; - } - nbgl_redrawObject((nbgl_obj_t *)keyboard,NULL,false); - nbgl_refreshSpecialWithPostRefresh(BLACK_AND_WHITE_REFRESH, POST_REFRESH_FORCE_POWER_ON); - } - else if (firstIndex == DIGITS_SWITCH_KEY_INDEX) { //switch to digits - keyboard->mode = MODE_DIGITS; - nbgl_redrawObject((nbgl_obj_t *)keyboard,NULL,false); - nbgl_refreshSpecialWithPostRefresh(BLACK_AND_WHITE_REFRESH, POST_REFRESH_FORCE_POWER_ON); - } - } - else if (keyboard->mode == MODE_DIGITS) { - if (firstIndex<26) { - keyboard->callback(kbd_digits[firstIndex]); - } - else if (firstIndex==SPECIAL_KEYS_INDEX) { - keyboard->mode = MODE_SPECIAL; - nbgl_redrawObject((nbgl_obj_t *)keyboard,NULL,false); - nbgl_refreshSpecialWithPostRefresh(BLACK_AND_WHITE_REFRESH, POST_REFRESH_FORCE_POWER_ON); - } - else if (firstIndex == DIGITS_SWITCH_KEY_INDEX) { // switch to letters - keyboard->mode = MODE_LETTERS; - nbgl_redrawObject((nbgl_obj_t *)keyboard,NULL,false); - nbgl_refreshSpecialWithPostRefresh(BLACK_AND_WHITE_REFRESH, POST_REFRESH_FORCE_POWER_ON); - } - } - else if (keyboard->mode == MODE_SPECIAL) { - if (firstIndex<26) { - keyboard->callback(kbd_specials[firstIndex]); - } - else if (firstIndex==SPECIAL_KEYS_INDEX) { - keyboard->mode = MODE_DIGITS; - nbgl_redrawObject((nbgl_obj_t *)keyboard,NULL,false); - nbgl_refreshSpecialWithPostRefresh(BLACK_AND_WHITE_REFRESH, POST_REFRESH_FORCE_POWER_ON); - } - else if (firstIndex == DIGITS_SWITCH_KEY_INDEX) { // switch to letters - keyboard->mode = MODE_LETTERS; - nbgl_redrawObject((nbgl_obj_t *)keyboard,NULL,false); - nbgl_refreshSpecialWithPostRefresh(BLACK_AND_WHITE_REFRESH, POST_REFRESH_FORCE_POWER_ON); - } - } - if (firstIndex == BACKSPACE_KEY_INDEX) { // backspace - keyboard->callback(BACKSPACE_KEY); - } - else if ((firstIndex == SPACE_KEY_INDEX)&&((keyboard->keyMask&(1<callback(' '); - } +void nbgl_keyboardTouchCallback(nbgl_obj_t *obj, nbgl_touchType_t eventType) +{ + uint8_t firstIndex, lastIndex; + nbgl_touchStatePosition_t *firstPosition, *lastPosition; + nbgl_keyboard_t *keyboard = (nbgl_keyboard_t *) obj; + + LOG_DEBUG(MISC_LOGGER, "keyboardTouchCallback(): eventType = %d\n", eventType); + if (eventType != TOUCHED) { + return; + } + if (nbgl_touchGetTouchedPosition(obj, &firstPosition, &lastPosition) == false) { + return; + } + // modify positions with keyboard position + firstPosition->x -= obj->area.x0; + firstPosition->y -= obj->area.y0; + lastPosition->x -= obj->area.x0; + lastPosition->y -= obj->area.y0; + + firstIndex = getKeyboardIndex(keyboard, firstPosition); + if (firstIndex > SPECIAL_KEYS_INDEX) { + return; + } + lastIndex = getKeyboardIndex(keyboard, lastPosition); + if (lastIndex > SPECIAL_KEYS_INDEX) { + return; + } + // if position of finger has moved durinng press to another "key", drop it + if (lastIndex != firstIndex) { + return; + } + + if (keyboard->mode == MODE_LETTERS) { + keyboardCase_t cur_casing = keyboard->casing; + // if the casing mode was upper (not-locked), go back to lower case + if ((keyboard->casing == UPPER_CASE) && (firstIndex != SHIFT_KEY_INDEX)) { + keyboard->casing = LOWER_CASE; + // just redraw, refresh will be done by client (user of keyboard) + nbgl_redrawObject((nbgl_obj_t *) keyboard, NULL, false); + keyboard->needsRefresh = true; + } + if ((firstIndex < 26) && ((keyboard->keyMask & (1 << firstIndex)) == 0)) { + keyboard->callback((cur_casing != LOWER_CASE) ? kbd_chars_upper[firstIndex] + : kbd_chars[firstIndex]); + } + else if (firstIndex == SHIFT_KEY_INDEX) { + switch (keyboard->casing) { + case LOWER_CASE: + keyboard->casing = UPPER_CASE; + break; + case UPPER_CASE: + keyboard->casing = LOCKED_UPPER_CASE; + break; + case LOCKED_UPPER_CASE: + keyboard->casing = LOWER_CASE; + break; + } + nbgl_redrawObject((nbgl_obj_t *) keyboard, NULL, false); + nbgl_refreshSpecialWithPostRefresh(BLACK_AND_WHITE_REFRESH, + POST_REFRESH_FORCE_POWER_ON); + } + else if (firstIndex == DIGITS_SWITCH_KEY_INDEX) { // switch to digits + keyboard->mode = MODE_DIGITS; + nbgl_redrawObject((nbgl_obj_t *) keyboard, NULL, false); + nbgl_refreshSpecialWithPostRefresh(BLACK_AND_WHITE_REFRESH, + POST_REFRESH_FORCE_POWER_ON); + } + } + else if (keyboard->mode == MODE_DIGITS) { + if (firstIndex < 26) { + keyboard->callback(kbd_digits[firstIndex]); + } + else if (firstIndex == SPECIAL_KEYS_INDEX) { + keyboard->mode = MODE_SPECIAL; + nbgl_redrawObject((nbgl_obj_t *) keyboard, NULL, false); + nbgl_refreshSpecialWithPostRefresh(BLACK_AND_WHITE_REFRESH, + POST_REFRESH_FORCE_POWER_ON); + } + else if (firstIndex == DIGITS_SWITCH_KEY_INDEX) { // switch to letters + keyboard->mode = MODE_LETTERS; + nbgl_redrawObject((nbgl_obj_t *) keyboard, NULL, false); + nbgl_refreshSpecialWithPostRefresh(BLACK_AND_WHITE_REFRESH, + POST_REFRESH_FORCE_POWER_ON); + } + } + else if (keyboard->mode == MODE_SPECIAL) { + if (firstIndex < 26) { + keyboard->callback(kbd_specials[firstIndex]); + } + else if (firstIndex == SPECIAL_KEYS_INDEX) { + keyboard->mode = MODE_DIGITS; + nbgl_redrawObject((nbgl_obj_t *) keyboard, NULL, false); + nbgl_refreshSpecialWithPostRefresh(BLACK_AND_WHITE_REFRESH, + POST_REFRESH_FORCE_POWER_ON); + } + else if (firstIndex == DIGITS_SWITCH_KEY_INDEX) { // switch to letters + keyboard->mode = MODE_LETTERS; + nbgl_redrawObject((nbgl_obj_t *) keyboard, NULL, false); + nbgl_refreshSpecialWithPostRefresh(BLACK_AND_WHITE_REFRESH, + POST_REFRESH_FORCE_POWER_ON); + } + } + if (firstIndex == BACKSPACE_KEY_INDEX) { // backspace + keyboard->callback(BACKSPACE_KEY); + } + else if ((firstIndex == SPACE_KEY_INDEX) + && ((keyboard->keyMask & (1 << SPACE_KEY_INDEX)) == 0)) { // space + keyboard->callback(' '); + } } /** @@ -570,13 +642,15 @@ void nbgl_keyboardTouchCallback(nbgl_obj_t *obj, nbgl_touchType_t eventType) { * * @param kbd the object to be drawned */ -void nbgl_objDrawKeyboard(nbgl_keyboard_t *kbd) { - kbd->obj.touchMask = (1 << TOUCHED); - kbd->needsRefresh = false; +void nbgl_objDrawKeyboard(nbgl_keyboard_t *kbd) +{ + kbd->obj.touchMask = (1 << TOUCHED); + kbd->needsRefresh = false; - keyboardDraw(kbd); + keyboardDraw(kbd); - // If a keyboard in the screen, exclude only top border from touch, to avoid missing touch on left keys - touch_exclude_borders(TOP_BORDER); + // If a keyboard in the screen, exclude only top border from touch, to avoid missing touch on + // left keys + touch_exclude_borders(TOP_BORDER); } -#endif // NBGL_KEYBOARD +#endif // NBGL_KEYBOARD diff --git a/lib_nbgl/src/nbgl_obj_keypad.c b/lib_nbgl/src/nbgl_obj_keypad.c index 6d9e95f68..cf37331f8 100644 --- a/lib_nbgl/src/nbgl_obj_keypad.c +++ b/lib_nbgl/src/nbgl_obj_keypad.c @@ -23,15 +23,18 @@ /********************* * DEFINES *********************/ -#define KEY_WIDTH (SCREEN_WIDTH/3) -#define DIGIT_OFFSET_Y (((KEYPAD_KEY_HEIGHT-48)/2)&0xFFC) +#define KEY_WIDTH (SCREEN_WIDTH / 3) +#define DIGIT_OFFSET_Y (((KEYPAD_KEY_HEIGHT - 48) / 2) & 0xFFC) -#define BACKSPACE_KEY_INDEX 10 -#define VALIDATE_KEY_INDEX 11 +#define BACKSPACE_KEY_INDEX 10 +#define VALIDATE_KEY_INDEX 11 // to save RAM we use 5 uint8, and 4 bits per digit (MSBs for odd digits, LSBs for even ones) -#define GET_DIGIT_INDEX(_keypad, _digit) ((_digit&1)?(_keypad->digitIndexes[_digit>>1]>>4):(_keypad->digitIndexes[_digit>>1]&0xF)) -#define SET_DIGIT_INDEX(_keypad, _digit, _index) (_keypad->digitIndexes[_digit>>1] |= (_digit&1)?(_index<<4):_index) +#define GET_DIGIT_INDEX(_keypad, _digit) \ + ((_digit & 1) ? (_keypad->digitIndexes[_digit >> 1] >> 4) \ + : (_keypad->digitIndexes[_digit >> 1] & 0xF)) +#define SET_DIGIT_INDEX(_keypad, _digit, _index) \ + (_keypad->digitIndexes[_digit >> 1] |= (_digit & 1) ? (_index << 4) : _index) extern uint8_t ramBuffer[GZLIB_UNCOMPRESSED_CHUNK]; @@ -51,172 +54,196 @@ extern uint8_t ramBuffer[GZLIB_UNCOMPRESSED_CHUNK]; * STATIC FUNCTIONS **********************/ -static uint8_t getKeypadIndex(uint16_t x, uint16_t y) { - uint8_t i=0; - // get index of key pressed - if (y < KEYPAD_KEY_HEIGHT) { - // 1st line: - i = 1 + x/KEY_WIDTH; - } - else if (y < (2*KEYPAD_KEY_HEIGHT)) { - // 2nd line: - i = 4 + x/KEY_WIDTH; - } - else if (y < (3*KEYPAD_KEY_HEIGHT)) { - // 3rd line: - i = 7 + x/KEY_WIDTH; - } - else if (y < (4*KEYPAD_KEY_HEIGHT)) { - // 4th line - if (xobj.area.backgroundColor; - rectArea.x0 = keypad->obj.area.x0; - rectArea.y0 = keypad->obj.area.y0; - rectArea.width = keypad->obj.area.width; - rectArea.height = keypad->obj.area.height; - nbgl_frontDrawRect(&rectArea); - - /// draw horizontal lines - rectArea.backgroundColor = keypad->obj.area.backgroundColor; - rectArea.x0 = keypad->obj.area.x0; - rectArea.y0 = keypad->obj.area.y0; - rectArea.width = keypad->obj.area.width; - rectArea.height = 4; - nbgl_frontDrawHorizontalLine(&rectArea, 0x1, keypad->borderColor); // 1st line (top) - rectArea.y0 += KEYPAD_KEY_HEIGHT; - nbgl_frontDrawHorizontalLine(&rectArea, 0x1, keypad->borderColor); // 2nd line - rectArea.y0 += KEYPAD_KEY_HEIGHT; - nbgl_frontDrawHorizontalLine(&rectArea, 0x1, keypad->borderColor); // 3rd line - rectArea.y0 += KEYPAD_KEY_HEIGHT; - nbgl_frontDrawHorizontalLine(&rectArea, 0x1, keypad->borderColor); // 4th line - - /// then draw 3 vertical lines - rectArea.backgroundColor = keypad->borderColor; - rectArea.x0 = keypad->obj.area.x0; - rectArea.y0 = keypad->obj.area.y0; - rectArea.width = 1; - rectArea.height = KEYPAD_KEY_HEIGHT*4; - nbgl_frontDrawRect(&rectArea); // 1st full line, on the left - rectArea.x0 += KEY_WIDTH; - nbgl_frontDrawRect(&rectArea); // 2nd line - rectArea.x0 += KEY_WIDTH; - nbgl_frontDrawRect(&rectArea); // 3rd line +static void keypadDrawGrid(nbgl_keypad_t *keypad) +{ + nbgl_area_t rectArea; + + // clean full area + rectArea.backgroundColor = keypad->obj.area.backgroundColor; + rectArea.x0 = keypad->obj.area.x0; + rectArea.y0 = keypad->obj.area.y0; + rectArea.width = keypad->obj.area.width; + rectArea.height = keypad->obj.area.height; + nbgl_frontDrawRect(&rectArea); + + /// draw horizontal lines + rectArea.backgroundColor = keypad->obj.area.backgroundColor; + rectArea.x0 = keypad->obj.area.x0; + rectArea.y0 = keypad->obj.area.y0; + rectArea.width = keypad->obj.area.width; + rectArea.height = 4; + nbgl_frontDrawHorizontalLine(&rectArea, 0x1, keypad->borderColor); // 1st line (top) + rectArea.y0 += KEYPAD_KEY_HEIGHT; + nbgl_frontDrawHorizontalLine(&rectArea, 0x1, keypad->borderColor); // 2nd line + rectArea.y0 += KEYPAD_KEY_HEIGHT; + nbgl_frontDrawHorizontalLine(&rectArea, 0x1, keypad->borderColor); // 3rd line + rectArea.y0 += KEYPAD_KEY_HEIGHT; + nbgl_frontDrawHorizontalLine(&rectArea, 0x1, keypad->borderColor); // 4th line + + /// then draw 3 vertical lines + rectArea.backgroundColor = keypad->borderColor; + rectArea.x0 = keypad->obj.area.x0; + rectArea.y0 = keypad->obj.area.y0; + rectArea.width = 1; + rectArea.height = KEYPAD_KEY_HEIGHT * 4; + nbgl_frontDrawRect(&rectArea); // 1st full line, on the left + rectArea.x0 += KEY_WIDTH; + nbgl_frontDrawRect(&rectArea); // 2nd line + rectArea.x0 += KEY_WIDTH; + nbgl_frontDrawRect(&rectArea); // 3rd line } +static void keypadDrawDigits(nbgl_keypad_t *keypad) +{ + uint8_t i; + nbgl_area_t rectArea; + char key_value; + + rectArea.backgroundColor = keypad->obj.area.backgroundColor; + rectArea.y0 = keypad->obj.area.y0 + DIGIT_OFFSET_Y; + + // First row of keys: 1 2 3 + for (i = 0; i < 3; i++) { + key_value = GET_DIGIT_INDEX(keypad, (i + 1)) + 0x30; + + rectArea.x0 = keypad->obj.area.x0 + i * KEY_WIDTH; + rectArea.x0 + += (KEY_WIDTH - nbgl_getCharWidth(BAGL_FONT_HM_ALPHA_MONO_MEDIUM_32px, &key_value)) / 2; + nbgl_drawText(&rectArea, + &key_value, + 1, + BAGL_FONT_HM_ALPHA_MONO_MEDIUM_32px, + keypad->enableDigits ? BLACK : WHITE); + } + // Second row: 4 5 6 + rectArea.y0 += KEYPAD_KEY_HEIGHT; + for (; i < 6; i++) { + key_value = GET_DIGIT_INDEX(keypad, (i + 1)) + 0x30; + rectArea.x0 = keypad->obj.area.x0 + (i - 3) * KEY_WIDTH; + rectArea.x0 + += (KEY_WIDTH - nbgl_getCharWidth(BAGL_FONT_HM_ALPHA_MONO_MEDIUM_32px, &key_value)) / 2; + nbgl_drawText(&rectArea, + &key_value, + 1, + BAGL_FONT_HM_ALPHA_MONO_MEDIUM_32px, + keypad->enableDigits ? BLACK : WHITE); + } + // Third row: 7 8 9 + rectArea.y0 += KEYPAD_KEY_HEIGHT; + for (; i < 9; i++) { + key_value = GET_DIGIT_INDEX(keypad, (i + 1)) + 0x30; + rectArea.x0 = keypad->obj.area.x0 + (i - 6) * KEY_WIDTH; + rectArea.x0 + += (KEY_WIDTH - nbgl_getCharWidth(BAGL_FONT_HM_ALPHA_MONO_MEDIUM_32px, &key_value)) / 2; + nbgl_drawText(&rectArea, + &key_value, + 1, + BAGL_FONT_HM_ALPHA_MONO_MEDIUM_32px, + keypad->enableDigits ? BLACK : WHITE); + } + // 4th raw, Backspace, 0 and Validate + // draw backspace + rectArea.width = C_backspace32px.width; + rectArea.height = C_backspace32px.height; + rectArea.bpp = NBGL_BPP_1; + rectArea.x0 = keypad->obj.area.x0 + (KEY_WIDTH - rectArea.width) / 2; + rectArea.y0 + = keypad->obj.area.y0 + KEYPAD_KEY_HEIGHT * 3 + (KEYPAD_KEY_HEIGHT - rectArea.height) / 2; +#if GLYPH_backspace32px_ISFILE + nbgl_frontDrawImageFile(&rectArea, + (uint8_t *) C_backspace32px.bitmap, + keypad->enableBackspace ? BLACK : WHITE, + ramBuffer); +#else + nbgl_frontDrawImage(&rectArea, + (uint8_t *) C_backspace32px.bitmap, + NO_TRANSFORMATION, + keypad->enableBackspace ? BLACK : WHITE); +#endif -static void keypadDrawDigits(nbgl_keypad_t *keypad) { - uint8_t i; - nbgl_area_t rectArea; - char key_value; - - rectArea.backgroundColor = keypad->obj.area.backgroundColor; - rectArea.y0 = keypad->obj.area.y0 + DIGIT_OFFSET_Y; - - // First row of keys: 1 2 3 - for (i=0;i<3;i++) { - key_value = GET_DIGIT_INDEX(keypad,(i+1)) + 0x30; - - rectArea.x0 = keypad->obj.area.x0 + i*KEY_WIDTH; - rectArea.x0 += (KEY_WIDTH-nbgl_getCharWidth(BAGL_FONT_HM_ALPHA_MONO_MEDIUM_32px,&key_value))/2; - nbgl_drawText(&rectArea, &key_value, - 1, BAGL_FONT_HM_ALPHA_MONO_MEDIUM_32px, - keypad->enableDigits ? BLACK : WHITE); - } - // Second row: 4 5 6 - rectArea.y0 += KEYPAD_KEY_HEIGHT; - for (;i<6;i++) { - key_value = GET_DIGIT_INDEX(keypad,(i+1)) + 0x30; - rectArea.x0 = keypad->obj.area.x0 + (i-3)*KEY_WIDTH; - rectArea.x0 += (KEY_WIDTH-nbgl_getCharWidth(BAGL_FONT_HM_ALPHA_MONO_MEDIUM_32px,&key_value))/2; - nbgl_drawText(&rectArea, &key_value, - 1, BAGL_FONT_HM_ALPHA_MONO_MEDIUM_32px, - keypad->enableDigits ? BLACK : WHITE); - } - // Third row: 7 8 9 - rectArea.y0 += KEYPAD_KEY_HEIGHT; - for (;i<9;i++) { - key_value = GET_DIGIT_INDEX(keypad,(i+1)) + 0x30; - rectArea.x0 = keypad->obj.area.x0 + (i-6)*KEY_WIDTH; - rectArea.x0 += (KEY_WIDTH-nbgl_getCharWidth(BAGL_FONT_HM_ALPHA_MONO_MEDIUM_32px,&key_value))/2; - nbgl_drawText(&rectArea, &key_value, - 1, BAGL_FONT_HM_ALPHA_MONO_MEDIUM_32px, - keypad->enableDigits ? BLACK : WHITE); - } - // 4th raw, Backspace, 0 and Validate - // draw backspace - rectArea.width = C_backspace32px.width; - rectArea.height = C_backspace32px.height; - rectArea.bpp = NBGL_BPP_1; - rectArea.x0 = keypad->obj.area.x0 + (KEY_WIDTH-rectArea.width)/2; - rectArea.y0 = keypad->obj.area.y0 + KEYPAD_KEY_HEIGHT*3 + (KEYPAD_KEY_HEIGHT-rectArea.height)/2; - #if GLYPH_backspace32px_ISFILE - nbgl_frontDrawImageFile(&rectArea,(uint8_t*)C_backspace32px.bitmap, keypad->enableBackspace?BLACK:WHITE, ramBuffer); - #else - nbgl_frontDrawImage(&rectArea,(uint8_t*)C_backspace32px.bitmap, NO_TRANSFORMATION, keypad->enableBackspace?BLACK:WHITE); - #endif - - // draw 0 - key_value = GET_DIGIT_INDEX(keypad,0)+0x30; - rectArea.x0 = keypad->obj.area.x0 + KEY_WIDTH; - rectArea.x0 += (KEY_WIDTH-nbgl_getCharWidth(BAGL_FONT_HM_ALPHA_MONO_MEDIUM_32px,&key_value))/2; - rectArea.y0 = keypad->obj.area.y0 + KEYPAD_KEY_HEIGHT*3 + DIGIT_OFFSET_Y; - nbgl_drawText(&rectArea, &key_value, - 1, BAGL_FONT_HM_ALPHA_MONO_MEDIUM_32px, - keypad->enableDigits ? BLACK : WHITE); - - // draw validate on gray with white background if not enabled - if (!keypad->enableValidate) { - rectArea.width = C_check32px.width; - rectArea.height = C_check32px.height; - rectArea.bpp = NBGL_BPP_1; - rectArea.x0 = keypad->obj.area.x0 + 2*KEY_WIDTH + (KEY_WIDTH-rectArea.width)/2; - rectArea.y0 = keypad->obj.area.y0 + KEYPAD_KEY_HEIGHT*3 + (KEYPAD_KEY_HEIGHT-rectArea.height)/2; - rectArea.backgroundColor = WHITE; - nbgl_frontDrawRect(&rectArea); - } - else { - // if enabled, draw icon in white on a black background - rectArea.backgroundColor = BLACK; - rectArea.x0 = keypad->obj.area.x0 + 2*KEY_WIDTH; - rectArea.y0 = keypad->obj.area.y0 + KEYPAD_KEY_HEIGHT*3; - rectArea.width = KEY_WIDTH; - rectArea.height = KEYPAD_KEY_HEIGHT; - nbgl_frontDrawRect(&rectArea); - rectArea.width = C_check32px.width; - rectArea.height = C_check32px.height; - rectArea.bpp = NBGL_BPP_1; - rectArea.x0 = keypad->obj.area.x0 + 2*KEY_WIDTH + (KEY_WIDTH-rectArea.width)/2; - rectArea.y0 = keypad->obj.area.y0 + KEYPAD_KEY_HEIGHT*3 + (KEYPAD_KEY_HEIGHT-rectArea.height)/2; + // draw 0 + key_value = GET_DIGIT_INDEX(keypad, 0) + 0x30; + rectArea.x0 = keypad->obj.area.x0 + KEY_WIDTH; + rectArea.x0 + += (KEY_WIDTH - nbgl_getCharWidth(BAGL_FONT_HM_ALPHA_MONO_MEDIUM_32px, &key_value)) / 2; + rectArea.y0 = keypad->obj.area.y0 + KEYPAD_KEY_HEIGHT * 3 + DIGIT_OFFSET_Y; + nbgl_drawText(&rectArea, + &key_value, + 1, + BAGL_FONT_HM_ALPHA_MONO_MEDIUM_32px, + keypad->enableDigits ? BLACK : WHITE); + + // draw validate on gray with white background if not enabled + if (!keypad->enableValidate) { + rectArea.width = C_check32px.width; + rectArea.height = C_check32px.height; + rectArea.bpp = NBGL_BPP_1; + rectArea.x0 = keypad->obj.area.x0 + 2 * KEY_WIDTH + (KEY_WIDTH - rectArea.width) / 2; + rectArea.y0 = keypad->obj.area.y0 + KEYPAD_KEY_HEIGHT * 3 + + (KEYPAD_KEY_HEIGHT - rectArea.height) / 2; + rectArea.backgroundColor = WHITE; + nbgl_frontDrawRect(&rectArea); + } + else { + // if enabled, draw icon in white on a black background + rectArea.backgroundColor = BLACK; + rectArea.x0 = keypad->obj.area.x0 + 2 * KEY_WIDTH; + rectArea.y0 = keypad->obj.area.y0 + KEYPAD_KEY_HEIGHT * 3; + rectArea.width = KEY_WIDTH; + rectArea.height = KEYPAD_KEY_HEIGHT; + nbgl_frontDrawRect(&rectArea); + rectArea.width = C_check32px.width; + rectArea.height = C_check32px.height; + rectArea.bpp = NBGL_BPP_1; + rectArea.x0 = keypad->obj.area.x0 + 2 * KEY_WIDTH + (KEY_WIDTH - rectArea.width) / 2; + rectArea.y0 = keypad->obj.area.y0 + KEYPAD_KEY_HEIGHT * 3 + + (KEYPAD_KEY_HEIGHT - rectArea.height) / 2; #if GLYPH_check32px_ISFILE - nbgl_frontDrawImageFile(&rectArea,(uint8_t*)C_check32px.bitmap, WHITE, ramBuffer); + nbgl_frontDrawImageFile(&rectArea, (uint8_t *) C_check32px.bitmap, WHITE, ramBuffer); #else - nbgl_frontDrawImage(&rectArea,(uint8_t*)C_check32px.bitmap,NO_TRANSFORMATION, WHITE); + nbgl_frontDrawImage(&rectArea, (uint8_t *) C_check32px.bitmap, NO_TRANSFORMATION, WHITE); #endif - } + } } -static void keypadDraw(nbgl_keypad_t *keypad) { - // At first, draw grid - keypadDrawGrid(keypad); +static void keypadDraw(nbgl_keypad_t *keypad) +{ + // At first, draw grid + keypadDrawGrid(keypad); - // then draw key content - keypadDrawDigits(keypad); + // then draw key content + keypadDrawDigits(keypad); } /********************** @@ -230,50 +257,61 @@ static void keypadDraw(nbgl_keypad_t *keypad) { * @param eventType type of touch (only TOUCHED is accepted) * @return none */ -void nbgl_keypadTouchCallback(nbgl_obj_t *obj, nbgl_touchType_t eventType) { - uint8_t firstIndex, lastIndex; - nbgl_touchStatePosition_t *firstPosition, *lastPosition; - nbgl_keypad_t *keypad = (nbgl_keypad_t *)obj; - - LOG_DEBUG(MISC_LOGGER,"nbgl_keypadTouchCallback(): eventType = %d\n",eventType); - if ((eventType != TOUCHED) && (eventType != TOUCH_PRESSED)) { - return; - } - if (nbgl_touchGetTouchedPosition(obj,&firstPosition,&lastPosition) == false) { - return; - } - - // use positions relative to keypad position - firstIndex = getKeypadIndex(firstPosition->x - obj->area.x0, firstPosition->y - obj->area.y0); - if (firstIndex > VALIDATE_KEY_INDEX) - return; - lastIndex = getKeypadIndex(lastPosition->x - obj->area.x0, lastPosition->y - obj->area.y0); - if (lastIndex > VALIDATE_KEY_INDEX) - return; - - // if position of finger has moved during press to another "key", drop it - if (lastIndex != firstIndex) - return; - - if ((firstIndex<10)&&(keypad->enableDigits)) { - // only call callback if event is TOUCHED, otherwise play tune on touch event (and not on release) - if (eventType == TOUCHED) - keypad->callback(GET_DIGIT_INDEX(keypad,firstIndex) + 0x30); - else - io_seproxyhal_play_tune(TUNE_TAP_CASUAL); - } - if ((firstIndex == BACKSPACE_KEY_INDEX)&&(keypad->enableBackspace)) { // backspace - // only call callback if event is TOUCHED, otherwise play tune on touch event (and not on release) - if (eventType == TOUCHED) - keypad->callback(BACKSPACE_KEY); - else - io_seproxyhal_play_tune(TUNE_TAP_CASUAL); - } - else if ((firstIndex == VALIDATE_KEY_INDEX)&&(keypad->enableValidate)) { // validate - // only call callback if event is TOUCHED - if (eventType == TOUCHED) - keypad->callback(VALIDATE_KEY); - } +void nbgl_keypadTouchCallback(nbgl_obj_t *obj, nbgl_touchType_t eventType) +{ + uint8_t firstIndex, lastIndex; + nbgl_touchStatePosition_t *firstPosition, *lastPosition; + nbgl_keypad_t *keypad = (nbgl_keypad_t *) obj; + + LOG_DEBUG(MISC_LOGGER, "nbgl_keypadTouchCallback(): eventType = %d\n", eventType); + if ((eventType != TOUCHED) && (eventType != TOUCH_PRESSED)) { + return; + } + if (nbgl_touchGetTouchedPosition(obj, &firstPosition, &lastPosition) == false) { + return; + } + + // use positions relative to keypad position + firstIndex = getKeypadIndex(firstPosition->x - obj->area.x0, firstPosition->y - obj->area.y0); + if (firstIndex > VALIDATE_KEY_INDEX) { + return; + } + lastIndex = getKeypadIndex(lastPosition->x - obj->area.x0, lastPosition->y - obj->area.y0); + if (lastIndex > VALIDATE_KEY_INDEX) { + return; + } + + // if position of finger has moved during press to another "key", drop it + if (lastIndex != firstIndex) { + return; + } + + if ((firstIndex < 10) && (keypad->enableDigits)) { + // only call callback if event is TOUCHED, otherwise play tune on touch event (and not on + // release) + if (eventType == TOUCHED) { + keypad->callback(GET_DIGIT_INDEX(keypad, firstIndex) + 0x30); + } + else { + io_seproxyhal_play_tune(TUNE_TAP_CASUAL); + } + } + if ((firstIndex == BACKSPACE_KEY_INDEX) && (keypad->enableBackspace)) { // backspace + // only call callback if event is TOUCHED, otherwise play tune on touch event (and not on + // release) + if (eventType == TOUCHED) { + keypad->callback(BACKSPACE_KEY); + } + else { + io_seproxyhal_play_tune(TUNE_TAP_CASUAL); + } + } + else if ((firstIndex == VALIDATE_KEY_INDEX) && (keypad->enableValidate)) { // validate + // only call callback if event is TOUCHED + if (eventType == TOUCHED) { + keypad->callback(VALIDATE_KEY); + } + } } /** @@ -282,38 +320,39 @@ void nbgl_keypadTouchCallback(nbgl_obj_t *obj, nbgl_touchType_t eventType) { * @param kpd keypad object to draw * @return the keypad keypad object */ -void nbgl_objDrawKeypad(nbgl_keypad_t *kpd) { - kpd->obj.touchMask = (1 << TOUCHED) | (1 << TOUCH_PRESSED); - - // if the object has not been already used, prepare indexes of digits - if (kpd->digitIndexes[0] == 0) { - uint32_t i; - if (kpd->shuffled) { - uint8_t shuffledDigits[10] = {0,1,2,3,4,5,6,7,8,9}; - - // modern version of the Fisher-Yates shuffle - for (i=0;i<9;i++) { - // pick a random number k in [i:9] intervale - uint32_t j = cx_rng_u32_range(i, 10); - uint8_t tmp = shuffledDigits[j]; - - // exchange shuffledDigits[i] and shuffledDigits[j] - shuffledDigits[j] = shuffledDigits[i]; - shuffledDigits[i] = tmp; - } - for (i=0;i<10;i++) { - // apply the permuted value to digit i - SET_DIGIT_INDEX(kpd,i,shuffledDigits[i]); - } - } - else { - // no shuffling - for (i=0;i<10;i++) { - SET_DIGIT_INDEX(kpd,i,i); - } +void nbgl_objDrawKeypad(nbgl_keypad_t *kpd) +{ + kpd->obj.touchMask = (1 << TOUCHED) | (1 << TOUCH_PRESSED); + + // if the object has not been already used, prepare indexes of digits + if (kpd->digitIndexes[0] == 0) { + uint32_t i; + if (kpd->shuffled) { + uint8_t shuffledDigits[10] = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9}; + + // modern version of the Fisher-Yates shuffle + for (i = 0; i < 9; i++) { + // pick a random number k in [i:9] intervale + uint32_t j = cx_rng_u32_range(i, 10); + uint8_t tmp = shuffledDigits[j]; + + // exchange shuffledDigits[i] and shuffledDigits[j] + shuffledDigits[j] = shuffledDigits[i]; + shuffledDigits[i] = tmp; + } + for (i = 0; i < 10; i++) { + // apply the permuted value to digit i + SET_DIGIT_INDEX(kpd, i, shuffledDigits[i]); + } + } + else { + // no shuffling + for (i = 0; i < 10; i++) { + SET_DIGIT_INDEX(kpd, i, i); + } + } } - } - keypadDraw(kpd); + keypadDraw(kpd); } -#endif // NBGL_KEYPAD +#endif // NBGL_KEYPAD diff --git a/lib_nbgl/src/nbgl_obj_pool.c b/lib_nbgl/src/nbgl_obj_pool.c index 172cf16bd..5d8e309a6 100644 --- a/lib_nbgl/src/nbgl_obj_pool.c +++ b/lib_nbgl/src/nbgl_obj_pool.c @@ -20,7 +20,7 @@ * @brief Max number of objects retrievable from pool * */ -#define OBJ_POOL_LEN 80 +#define OBJ_POOL_LEN 80 /** * @brief Max number of objects pointers usable for container pool * @@ -34,24 +34,23 @@ **********************/ typedef struct { - union { - nbgl_obj_t obj; - nbgl_radio_t radioObj; - nbgl_switch_t switchObj; - nbgl_text_area_t textAreaObj; - nbgl_button_t buttonObj; - nbgl_progress_bar_t progressBarObj; - nbgl_page_indicator_t navBarObj; - nbgl_container_t containerObj; - nbgl_image_t imageObj; - nbgl_line_t lineObj; - nbgl_keyboard_t keyboardObj; - nbgl_keypad_t keypadObj; - nbgl_spinner_t spinnerObj; - }; + union { + nbgl_obj_t obj; + nbgl_radio_t radioObj; + nbgl_switch_t switchObj; + nbgl_text_area_t textAreaObj; + nbgl_button_t buttonObj; + nbgl_progress_bar_t progressBarObj; + nbgl_page_indicator_t navBarObj; + nbgl_container_t containerObj; + nbgl_image_t imageObj; + nbgl_line_t lineObj; + nbgl_keyboard_t keyboardObj; + nbgl_keypad_t keypadObj; + nbgl_spinner_t spinnerObj; + }; } genericObj_t; - /********************** * STATIC PROTOTYPES **********************/ @@ -68,7 +67,7 @@ static uint8_t objPoolLayers[OBJ_POOL_LEN]; static uint8_t nbUsedObjsInPool = 0; // This is the pool of graphic objects pointers for containers -static nbgl_obj_t* objContainerPool[OBJ_CONTAINER_POOL_LEN]; +static nbgl_obj_t *objContainerPool[OBJ_CONTAINER_POOL_LEN]; // This is the array of layer per object pointers in pool static uint8_t objPointersPoolLayers[OBJ_CONTAINER_POOL_LEN]; // This is the number of graphic objects currently used from the objContainerPool @@ -107,128 +106,146 @@ static bool initialized; * @brief Release the objects from the pool for the given layer * @param layer layer to release object from */ -void nbgl_objPoolRelease(uint8_t layer) { - uint8_t i; - LOG_DEBUG(OBJ_POOL_LOGGER,"nbgl_objPoolRelease(): used objs in pool %d, for layer (%d)\n",nbUsedObjsInPool,layer); - if (nbUsedObjsInPool == 0) { - return; - } - for (i=0;itype = type; - objPoolLayers[i] = layer; - nbUsedObjsInPool++; - return obj; +nbgl_obj_t *nbgl_objPoolGet(nbgl_obj_type_t type, uint8_t layer) +{ + uint8_t i; + nbgl_obj_t *obj; + + if (initialized == false) { + memset(objPoolLayers, INVALID_LAYER, OBJ_POOL_LEN); + memset(objPointersPoolLayers, INVALID_LAYER, OBJ_CONTAINER_POOL_LEN); + initialized = true; } - } - //should never happen - return NULL; + if (nbUsedObjsInPool == (OBJ_POOL_LEN - 1)) { + LOG_FATAL( + OBJ_POOL_LOGGER, "nbgl_objPoolGet(): NO ENOUGH OBJ in POOL. max = %d\n", OBJ_POOL_LEN); + // TODO: crash here? + return NULL; + } + for (i = 0; i < OBJ_POOL_LEN; i++) { + if (INVALID_LAYER == objPoolLayers[i]) { + obj = &objPool[i].obj; + memset(obj, 0, sizeof(genericObj_t)); + obj->type = type; + objPoolLayers[i] = layer; + nbUsedObjsInPool++; + return obj; + } + } + // should never happen + return NULL; } /** - * @brief Gets a link to the previous object in the pool, for the given layer. (to be used with care) + * @brief Gets a link to the previous object in the pool, for the given layer. (to be used with + * care) * @param obj object to get previous from * @param layer layer (screen) in which to retrieve the object * @return a pointer to the previous object in the pool */ -nbgl_obj_t* nbgl_objPoolGetPrevious(nbgl_obj_t* obj, uint8_t layer) { - uint8_t index; - - // retrieve object index - index = (genericObj_t*)obj - objPool; - - while (index>0) { - index--; - if (objPoolLayers[index] == layer) { - return &objPool[index].obj; +nbgl_obj_t *nbgl_objPoolGetPrevious(nbgl_obj_t *obj, uint8_t layer) +{ + uint8_t index; + + // retrieve object index + index = (genericObj_t *) obj - objPool; + + while (index > 0) { + index--; + if (objPoolLayers[index] == layer) { + return &objPool[index].obj; + } } - } - return NULL; + return NULL; } /** - * @brief Gets nbObjects new graphic object from the pool, with the given type, for the given layer (screen). The type field of the object is set. + * @brief Gets nbObjects new graphic object from the pool, with the given type, for the given layer + * (screen). The type field of the object is set. * @param type type of objects to get from the pool * @param nbObjs number of objects to get from the pool * @param layer layer (screen) to get the object to * @param objArray array of objs pointers * @return >= 0 if OK */ -int nbgl_objPoolGetArray(nbgl_obj_type_t type, uint8_t nbObjs, uint8_t layer, nbgl_obj_t** objArray) { - uint8_t i; - - if ((nbUsedObjsInPool+nbObjs)>=OBJ_POOL_LEN) { - LOG_FATAL(OBJ_POOL_LOGGER,"nbgl_objPoolGetArray(): NO ENOUGH OBJ in POOL. Asked: %d, max = %d\n",(nbUsedObjsInPool+nbObjs),OBJ_POOL_LEN); - // TODO: crash here? - return -1; - } - for (i=0;i= OBJ_POOL_LEN) { + LOG_FATAL(OBJ_POOL_LOGGER, + "nbgl_objPoolGetArray(): NO ENOUGH OBJ in POOL. Asked: %d, max = %d\n", + (nbUsedObjsInPool + nbObjs), + OBJ_POOL_LEN); + // TODO: crash here? + return -1; + } + for (i = 0; i < nbObjs; i++) { + objArray[i] = nbgl_objPoolGet(type, layer); + } - return 0; + return 0; } /** * @brief Release the objects pointers from the pool for the given layer * @param layer layer to release objects pointers from */ -void nbgl_containerPoolRelease(uint8_t layer) { - uint8_t i; - LOG_DEBUG(OBJ_POOL_LOGGER,"nbgl_containerPoolRelease(): %d containers in pool\n",nbUsedObjsInContainerPool); - if (nbUsedObjsInContainerPool == 0) { - return; - } - for (i=0;i=(OBJ_CONTAINER_POOL_LEN-1)) { - LOG_FATAL(OBJ_POOL_LOGGER,"nbgl_containerPoolGet(): NO ENOUGH OBJ in POOL. Asked: %d, max = %d\n",(nbUsedObjsInContainerPool+nbObjs),OBJ_CONTAINER_POOL_LEN); - // TODO: crash here? - return NULL; - } - while(i= (OBJ_CONTAINER_POOL_LEN - 1)) { + LOG_FATAL(OBJ_POOL_LOGGER, + "nbgl_containerPoolGet(): NO ENOUGH OBJ in POOL. Asked: %d, max = %d\n", + (nbUsedObjsInContainerPool + nbObjs), + OBJ_CONTAINER_POOL_LEN); + // TODO: crash here? + return NULL; } - i++; - if (nbContiguousFree == nbObjs) { - container = &objContainerPool[i-nbObjs]; - memset(container,0,nbObjs*sizeof(nbgl_obj_t*)); - // mark slots as used - memset(&objPointersPoolLayers[i-nbObjs],layer,nbObjs); - nbUsedObjsInContainerPool+=nbObjs; - return container; + while (i < OBJ_CONTAINER_POOL_LEN) { + if (INVALID_LAYER == objPointersPoolLayers[i]) { + nbContiguousFree++; + } + else { + nbContiguousFree = 0; + } + i++; + if (nbContiguousFree == nbObjs) { + container = &objContainerPool[i - nbObjs]; + memset(container, 0, nbObjs * sizeof(nbgl_obj_t *)); + // mark slots as used + memset(&objPointersPoolLayers[i - nbObjs], layer, nbObjs); + nbUsedObjsInContainerPool += nbObjs; + return container; + } } - } - return NULL; + return NULL; } /** * @brief returns the number of containers currently used in the pool */ -uint8_t nbgl_containerPoolGetNbUsed(uint8_t layer) { - uint8_t i,nbFound=0; - for (i=0;ititle != NULL) { - nbgl_layoutBar_t bar; - bar.text = content->title; - bar.subText = NULL; - bar.iconRight = NULL; - bar.iconLeft = content->isTouchableTitle? &C_leftArrow32px:NULL; - bar.token = content->titleToken; - bar.centered = true; - bar.inactive = false; - bar.tuneId = content->tuneId; - nbgl_layoutAddTouchableBar(layout, &bar); - nbgl_layoutAddSeparationLine(layout); - } - switch (content->type) { - case INFO_LONG_PRESS: - { - nbgl_layoutCenteredInfo_t centeredInfo; - centeredInfo.icon = content->infoLongPress.icon; - centeredInfo.text1 = content->infoLongPress.text; - centeredInfo.text2 = NULL; - centeredInfo.text3 = NULL; - centeredInfo.style = LARGE_CASE_INFO; - centeredInfo.offsetY = -32; - centeredInfo.onTop = false; - nbgl_layoutAddCenteredInfo(layout,¢eredInfo); - nbgl_layoutAddLongPressButton(layout,content->infoLongPress.longPressText,content->infoLongPress.longPressToken,content->infoLongPress.tuneId); - break; - } - case INFO_BUTTON: - { - nbgl_layoutCenteredInfo_t centeredInfo; - nbgl_layoutButton_t buttonInfo; - - centeredInfo.icon = content->infoButton.icon; - centeredInfo.text1 = content->infoButton.text; - centeredInfo.text2 = NULL; - centeredInfo.text3 = NULL; - centeredInfo.style = LARGE_CASE_INFO; - centeredInfo.offsetY = -40; - centeredInfo.onTop = false; - nbgl_layoutAddCenteredInfo(layout,¢eredInfo); - - buttonInfo.fittingContent = false; - buttonInfo.icon = NULL; - buttonInfo.onBottom = true; - buttonInfo.style = BLACK_BACKGROUND; - buttonInfo.text = content->infoButton.buttonText; - buttonInfo.token = content->infoButton.buttonToken; - buttonInfo.tuneId = content->infoButton.tuneId; - nbgl_layoutAddButton(layout,&buttonInfo); - break; - } - case CENTERED_INFO: - nbgl_layoutAddCenteredInfo(layout,&content->centeredInfo); - break; - case TAG_VALUE_LIST: - nbgl_layoutAddTagValueList(layout,&content->tagValueList); - break; - case TAG_VALUE_DETAILS: - { - uint16_t nbLines = nbgl_getTextNbLinesInWidth(content->tagValueDetails.tagValueList.smallCaseForValue? BAGL_FONT_INTER_REGULAR_24px:BAGL_FONT_INTER_MEDIUM_32px, - content->tagValueDetails.tagValueList.pairs[0].value, - SCREEN_WIDTH-2*BORDER_MARGIN, - content->tagValueDetails.tagValueList.wrapping); - // automatically display a button if content is longer that nbMaxLinesForValue - if (nbLines > (content->tagValueDetails.tagValueList.nbMaxLinesForValue)) { - nbgl_layoutButton_t buttonInfo; - content->tagValueDetails.tagValueList.nbMaxLinesForValue -= 3; - nbgl_layoutAddTagValueList(layout,&content->tagValueDetails.tagValueList); - buttonInfo.fittingContent = true; - buttonInfo.icon = content->tagValueDetails.detailsButtonIcon; - buttonInfo.style = WHITE_BACKGROUND; - buttonInfo.text = content->tagValueDetails.detailsButtonText; - buttonInfo.token = content->tagValueDetails.detailsButtonToken; - buttonInfo.tuneId = content->tagValueDetails.tuneId; - buttonInfo.onBottom = false; - nbgl_layoutAddButton(layout,&buttonInfo); - } - else { - nbgl_layoutAddTagValueList(layout,&content->tagValueDetails.tagValueList); - } - break; - } - case TAG_VALUE_CONFIRM: - { - nbgl_layoutButton_t buttonInfo; - nbgl_layoutAddTagValueList(layout,&content->tagValueConfirm.tagValueList); - if (content->tagValueConfirm.detailsButtonText != NULL) { - buttonInfo.fittingContent = true; - buttonInfo.icon = content->tagValueConfirm.detailsButtonIcon; - buttonInfo.style = WHITE_BACKGROUND; - buttonInfo.text = content->tagValueConfirm.detailsButtonText; - buttonInfo.token = content->tagValueConfirm.detailsButtonToken; - buttonInfo.tuneId = content->tagValueConfirm.tuneId; - buttonInfo.onBottom = false; - nbgl_layoutAddButton(layout,&buttonInfo); - } - if (content->tagValueConfirm.confirmationText != NULL) { - buttonInfo.fittingContent = false; - buttonInfo.icon = NULL; - buttonInfo.style = BLACK_BACKGROUND; - buttonInfo.text = content->tagValueConfirm.confirmationText; - buttonInfo.token = content->tagValueConfirm.confirmationToken; - buttonInfo.tuneId = content->tagValueConfirm.tuneId; - buttonInfo.onBottom = true; - nbgl_layoutAddButton(layout,&buttonInfo); - } - break; - } - case SWITCHES_LIST: - { - uint8_t i; - for (i=0;iswitchesList.nbSwitches;i++) { - nbgl_layoutAddSwitch(layout, &content->switchesList.switches[i]); - nbgl_layoutAddSeparationLine(layout); - } - break; - } - case INFOS_LIST: - { - uint8_t i; - for (i=0;iinfosList.nbInfos;i++) { - nbgl_layoutAddText(layout,content->infosList.infoTypes[i],content->infosList.infoContents[i]); - nbgl_layoutAddSeparationLine(layout); - } - break; - } - case CHOICES_LIST: - nbgl_layoutAddRadioChoice(layout,&content->choicesList); - break; - case BARS_LIST: - { - uint8_t i; - for (i=0;ibarsList.nbBars;i++) { +static void addContent(nbgl_pageContent_t *content, nbgl_layout_t *layout) +{ + if (content->title != NULL) { nbgl_layoutBar_t bar; - bar.text = content->barsList.barTexts[i]; - bar.subText = NULL; - bar.iconRight = &C_Next32px; - bar.iconLeft = NULL; - bar.token = content->barsList.tokens[i]; - bar.centered = false; - bar.tuneId = content->barsList.tuneId; + bar.text = content->title; + bar.subText = NULL; + bar.iconRight = NULL; + bar.iconLeft = content->isTouchableTitle ? &C_leftArrow32px : NULL; + bar.token = content->titleToken; + bar.centered = true; + bar.inactive = false; + bar.tuneId = content->tuneId; nbgl_layoutAddTouchableBar(layout, &bar); nbgl_layoutAddSeparationLine(layout); - } - break; } - } + switch (content->type) { + case INFO_LONG_PRESS: { + nbgl_layoutCenteredInfo_t centeredInfo; + centeredInfo.icon = content->infoLongPress.icon; + centeredInfo.text1 = content->infoLongPress.text; + centeredInfo.text2 = NULL; + centeredInfo.text3 = NULL; + centeredInfo.style = LARGE_CASE_INFO; + centeredInfo.offsetY = -32; + centeredInfo.onTop = false; + nbgl_layoutAddCenteredInfo(layout, ¢eredInfo); + nbgl_layoutAddLongPressButton(layout, + content->infoLongPress.longPressText, + content->infoLongPress.longPressToken, + content->infoLongPress.tuneId); + break; + } + case INFO_BUTTON: { + nbgl_layoutCenteredInfo_t centeredInfo; + nbgl_layoutButton_t buttonInfo; + + centeredInfo.icon = content->infoButton.icon; + centeredInfo.text1 = content->infoButton.text; + centeredInfo.text2 = NULL; + centeredInfo.text3 = NULL; + centeredInfo.style = LARGE_CASE_INFO; + centeredInfo.offsetY = -40; + centeredInfo.onTop = false; + nbgl_layoutAddCenteredInfo(layout, ¢eredInfo); + + buttonInfo.fittingContent = false; + buttonInfo.icon = NULL; + buttonInfo.onBottom = true; + buttonInfo.style = BLACK_BACKGROUND; + buttonInfo.text = content->infoButton.buttonText; + buttonInfo.token = content->infoButton.buttonToken; + buttonInfo.tuneId = content->infoButton.tuneId; + nbgl_layoutAddButton(layout, &buttonInfo); + break; + } + case CENTERED_INFO: + nbgl_layoutAddCenteredInfo(layout, &content->centeredInfo); + break; + case TAG_VALUE_LIST: + nbgl_layoutAddTagValueList(layout, &content->tagValueList); + break; + case TAG_VALUE_DETAILS: { + uint16_t nbLines + = nbgl_getTextNbLinesInWidth(content->tagValueDetails.tagValueList.smallCaseForValue + ? BAGL_FONT_INTER_REGULAR_24px + : BAGL_FONT_INTER_MEDIUM_32px, + content->tagValueDetails.tagValueList.pairs[0].value, + SCREEN_WIDTH - 2 * BORDER_MARGIN, + content->tagValueDetails.tagValueList.wrapping); + // automatically display a button if content is longer that nbMaxLinesForValue + if (nbLines > (content->tagValueDetails.tagValueList.nbMaxLinesForValue)) { + nbgl_layoutButton_t buttonInfo; + content->tagValueDetails.tagValueList.nbMaxLinesForValue -= 3; + nbgl_layoutAddTagValueList(layout, &content->tagValueDetails.tagValueList); + buttonInfo.fittingContent = true; + buttonInfo.icon = content->tagValueDetails.detailsButtonIcon; + buttonInfo.style = WHITE_BACKGROUND; + buttonInfo.text = content->tagValueDetails.detailsButtonText; + buttonInfo.token = content->tagValueDetails.detailsButtonToken; + buttonInfo.tuneId = content->tagValueDetails.tuneId; + buttonInfo.onBottom = false; + nbgl_layoutAddButton(layout, &buttonInfo); + } + else { + nbgl_layoutAddTagValueList(layout, &content->tagValueDetails.tagValueList); + } + break; + } + case TAG_VALUE_CONFIRM: { + nbgl_layoutButton_t buttonInfo; + nbgl_layoutAddTagValueList(layout, &content->tagValueConfirm.tagValueList); + if (content->tagValueConfirm.detailsButtonText != NULL) { + buttonInfo.fittingContent = true; + buttonInfo.icon = content->tagValueConfirm.detailsButtonIcon; + buttonInfo.style = WHITE_BACKGROUND; + buttonInfo.text = content->tagValueConfirm.detailsButtonText; + buttonInfo.token = content->tagValueConfirm.detailsButtonToken; + buttonInfo.tuneId = content->tagValueConfirm.tuneId; + buttonInfo.onBottom = false; + nbgl_layoutAddButton(layout, &buttonInfo); + } + if (content->tagValueConfirm.confirmationText != NULL) { + buttonInfo.fittingContent = false; + buttonInfo.icon = NULL; + buttonInfo.style = BLACK_BACKGROUND; + buttonInfo.text = content->tagValueConfirm.confirmationText; + buttonInfo.token = content->tagValueConfirm.confirmationToken; + buttonInfo.tuneId = content->tagValueConfirm.tuneId; + buttonInfo.onBottom = true; + nbgl_layoutAddButton(layout, &buttonInfo); + } + break; + } + case SWITCHES_LIST: { + uint8_t i; + for (i = 0; i < content->switchesList.nbSwitches; i++) { + nbgl_layoutAddSwitch(layout, &content->switchesList.switches[i]); + nbgl_layoutAddSeparationLine(layout); + } + break; + } + case INFOS_LIST: { + uint8_t i; + for (i = 0; i < content->infosList.nbInfos; i++) { + nbgl_layoutAddText( + layout, content->infosList.infoTypes[i], content->infosList.infoContents[i]); + nbgl_layoutAddSeparationLine(layout); + } + break; + } + case CHOICES_LIST: + nbgl_layoutAddRadioChoice(layout, &content->choicesList); + break; + case BARS_LIST: { + uint8_t i; + for (i = 0; i < content->barsList.nbBars; i++) { + nbgl_layoutBar_t bar; + bar.text = content->barsList.barTexts[i]; + bar.subText = NULL; + bar.iconRight = &C_Next32px; + bar.iconLeft = NULL; + bar.token = content->barsList.tokens[i]; + bar.centered = false; + bar.tuneId = content->barsList.tuneId; + nbgl_layoutAddTouchableBar(layout, &bar); + nbgl_layoutAddSeparationLine(layout); + } + break; + } + } } /********************** @@ -192,63 +193,67 @@ static void addContent(nbgl_pageContent_t* content, nbgl_layout_t *layout) { * @param tapActionToken token passed to onActionCallback, on a tap event * @return the page context (or NULL if error) */ -nbgl_page_t* nbgl_pageDrawLedgerInfo(nbgl_layoutTouchCallback_t onActionCallback, const nbgl_screenTickerConfiguration_t *ticker, const char* text, int tapActionToken) { - nbgl_layoutDescription_t layoutDescription; - nbgl_layout_t *layout; - nbgl_layoutCenteredInfo_t centeredInfo = { - .text1 = text, - .text2 = NULL, - .text3 = NULL, - .style = LEDGER_INFO, - .icon = NULL, - .offsetY = 0 - }; - - layoutDescription.modal = false; - layoutDescription.withLeftBorder = true; - - layoutDescription.onActionCallback = onActionCallback; - layoutDescription.tapActionText = ""; - layoutDescription.tapActionToken = tapActionToken; - layoutDescription.tapTuneId = TUNE_TAP_CASUAL; - - layoutDescription.ticker.tickerCallback = ticker->tickerCallback; - layoutDescription.ticker.tickerIntervale = ticker->tickerIntervale; - layoutDescription.ticker.tickerValue = ticker->tickerValue; - layout = nbgl_layoutGet(&layoutDescription); - - nbgl_layoutAddCenteredInfo(layout, ¢eredInfo); - - nbgl_layoutDraw(layout); - - return (nbgl_page_t*)layout; +nbgl_page_t *nbgl_pageDrawLedgerInfo(nbgl_layoutTouchCallback_t onActionCallback, + const nbgl_screenTickerConfiguration_t *ticker, + const char *text, + int tapActionToken) +{ + nbgl_layoutDescription_t layoutDescription; + nbgl_layout_t *layout; + nbgl_layoutCenteredInfo_t centeredInfo = {.text1 = text, + .text2 = NULL, + .text3 = NULL, + .style = LEDGER_INFO, + .icon = NULL, + .offsetY = 0}; + + layoutDescription.modal = false; + layoutDescription.withLeftBorder = true; + + layoutDescription.onActionCallback = onActionCallback; + layoutDescription.tapActionText = ""; + layoutDescription.tapActionToken = tapActionToken; + layoutDescription.tapTuneId = TUNE_TAP_CASUAL; + + layoutDescription.ticker.tickerCallback = ticker->tickerCallback; + layoutDescription.ticker.tickerIntervale = ticker->tickerIntervale; + layoutDescription.ticker.tickerValue = ticker->tickerValue; + layout = nbgl_layoutGet(&layoutDescription); + + nbgl_layoutAddCenteredInfo(layout, ¢eredInfo); + + nbgl_layoutDraw(layout); + + return (nbgl_page_t *) layout; } /** - * @brief draw a spinner page with the given parameters. The spinner will "turn" automatically every 800 ms + * @brief draw a spinner page with the given parameters. The spinner will "turn" automatically every + * 800 ms * * @param onActionCallback common callback for all actions on this page * @param text text to use under spinner * @return the page context (or NULL if error) */ -nbgl_page_t* nbgl_pageDrawSpinner(nbgl_layoutTouchCallback_t onActionCallback, const char* text) { - nbgl_layoutDescription_t layoutDescription; - nbgl_layout_t *layout; +nbgl_page_t *nbgl_pageDrawSpinner(nbgl_layoutTouchCallback_t onActionCallback, const char *text) +{ + nbgl_layoutDescription_t layoutDescription; + nbgl_layout_t *layout; - layoutDescription.modal = false; - layoutDescription.withLeftBorder = true; + layoutDescription.modal = false; + layoutDescription.withLeftBorder = true; - layoutDescription.onActionCallback = onActionCallback; - layoutDescription.tapActionText = NULL; + layoutDescription.onActionCallback = onActionCallback; + layoutDescription.tapActionText = NULL; - layoutDescription.ticker.tickerCallback = NULL; - layout = nbgl_layoutGet(&layoutDescription); + layoutDescription.ticker.tickerCallback = NULL; + layout = nbgl_layoutGet(&layoutDescription); - nbgl_layoutAddSpinner(layout, text, false); + nbgl_layoutAddSpinner(layout, text, false); - nbgl_layoutDraw(layout); + nbgl_layoutDraw(layout); - return (nbgl_page_t*)layout; + return (nbgl_page_t *) layout; } /** @@ -260,154 +265,159 @@ nbgl_page_t* nbgl_pageDrawSpinner(nbgl_layoutTouchCallback_t onActionCallback, c * @param info structure describing the centered info and other controls of this page * @return the page context (or NULL if error) */ -nbgl_page_t* nbgl_pageDrawInfo(nbgl_layoutTouchCallback_t onActionCallback, const nbgl_screenTickerConfiguration_t *ticker, const nbgl_pageInfoDescription_t *info) { - nbgl_layoutDescription_t layoutDescription; - nbgl_layout_t *layout; - - layoutDescription.modal = false; - layoutDescription.withLeftBorder = true; - - layoutDescription.onActionCallback = onActionCallback; - layoutDescription.tapActionText = info->tapActionText; - layoutDescription.tapActionToken = info->tapActionToken; - layoutDescription.tapTuneId = info->tuneId; - - if (ticker != NULL) { - layoutDescription.ticker.tickerCallback = ticker->tickerCallback; - layoutDescription.ticker.tickerIntervale = ticker->tickerIntervale; - layoutDescription.ticker.tickerValue = ticker->tickerValue; - } - else { - layoutDescription.ticker.tickerCallback = NULL; - } - layout = nbgl_layoutGet(&layoutDescription); - - nbgl_layoutAddCenteredInfo(layout,&info->centeredInfo); - - // if action button but not QUIT_APP_TEXT bottom button, use a small black button - if ((info->actionButtonText != NULL) && (info->bottomButtonStyle != QUIT_APP_TEXT)) { - nbgl_layoutButton_t buttonInfo = { - .fittingContent = true, - .icon = NULL, - .onBottom = false, - .style = BLACK_BACKGROUND, - .text = info->actionButtonText, - .token = info->bottomButtonsToken, - .tuneId = info->tuneId - }; - nbgl_layoutAddButton(layout,&buttonInfo); - } - - if (info->footerText != NULL) { - nbgl_layoutAddFooter(layout, PIC(info->footerText), info->footerToken, info->tuneId); - } - if (info->topRightStyle != NO_BUTTON_STYLE) { - const nbgl_icon_details_t *icon; - if (info->topRightStyle == SETTINGS_ICON) - icon = &C_wheel32px; - else if (info->topRightStyle == INFO_ICON) - icon = &C_info_i_32px; - else if (info->topRightStyle == QUIT_ICON) - icon = &C_cross32px; - else - return NULL; - nbgl_layoutAddTopRightButton(layout, PIC(icon), info->topRightToken, info->tuneId); - } - if (info->bottomButtonStyle == QUIT_APP_TEXT) { - // if action button and QUIT_APP_TEXT bottom button, use a pair of choice buttons - if ((info->actionButtonText != NULL)) { - nbgl_layoutChoiceButtons_t buttonsInfo = { - .topText = info->actionButtonText, - .bottomText = "Quit app", - .token = info->bottomButtonsToken, - .style = BOTH_ROUNDED_STYLE, - .tuneId = info->tuneId - }; - nbgl_layoutAddChoiceButtons(layout,&buttonsInfo); +nbgl_page_t *nbgl_pageDrawInfo(nbgl_layoutTouchCallback_t onActionCallback, + const nbgl_screenTickerConfiguration_t *ticker, + const nbgl_pageInfoDescription_t *info) +{ + nbgl_layoutDescription_t layoutDescription; + nbgl_layout_t *layout; + + layoutDescription.modal = false; + layoutDescription.withLeftBorder = true; + + layoutDescription.onActionCallback = onActionCallback; + layoutDescription.tapActionText = info->tapActionText; + layoutDescription.tapActionToken = info->tapActionToken; + layoutDescription.tapTuneId = info->tuneId; + + if (ticker != NULL) { + layoutDescription.ticker.tickerCallback = ticker->tickerCallback; + layoutDescription.ticker.tickerIntervale = ticker->tickerIntervale; + layoutDescription.ticker.tickerValue = ticker->tickerValue; } else { - nbgl_layoutButton_t buttonInfo = { - .fittingContent = false, - .icon = NULL, - .onBottom = true, - .style = WHITE_BACKGROUND, - .text = "Quit app", - .token = info->bottomButtonsToken, - .tuneId = info->tuneId - }; - nbgl_layoutAddButton(layout,&buttonInfo); + layoutDescription.ticker.tickerCallback = NULL; } - } - else if (info->bottomButtonStyle != NO_BUTTON_STYLE) { - const nbgl_icon_details_t *icon; - if (info->bottomButtonStyle == SETTINGS_ICON) - icon = &C_wheel32px; - else if (info->bottomButtonStyle == INFO_ICON) - icon = &C_info_i_32px; - else if (info->bottomButtonStyle == QUIT_ICON) - icon = &C_cross32px; - else - return NULL; - nbgl_layoutAddBottomButton(layout, PIC(icon), info->bottomButtonsToken, false, info->tuneId); - } - nbgl_layoutDraw(layout); - - return (nbgl_page_t*)layout; + layout = nbgl_layoutGet(&layoutDescription); + + nbgl_layoutAddCenteredInfo(layout, &info->centeredInfo); + + // if action button but not QUIT_APP_TEXT bottom button, use a small black button + if ((info->actionButtonText != NULL) && (info->bottomButtonStyle != QUIT_APP_TEXT)) { + nbgl_layoutButton_t buttonInfo = {.fittingContent = true, + .icon = NULL, + .onBottom = false, + .style = BLACK_BACKGROUND, + .text = info->actionButtonText, + .token = info->bottomButtonsToken, + .tuneId = info->tuneId}; + nbgl_layoutAddButton(layout, &buttonInfo); + } + + if (info->footerText != NULL) { + nbgl_layoutAddFooter(layout, PIC(info->footerText), info->footerToken, info->tuneId); + } + if (info->topRightStyle != NO_BUTTON_STYLE) { + const nbgl_icon_details_t *icon; + if (info->topRightStyle == SETTINGS_ICON) { + icon = &C_wheel32px; + } + else if (info->topRightStyle == INFO_ICON) { + icon = &C_info_i_32px; + } + else if (info->topRightStyle == QUIT_ICON) { + icon = &C_cross32px; + } + else { + return NULL; + } + nbgl_layoutAddTopRightButton(layout, PIC(icon), info->topRightToken, info->tuneId); + } + if (info->bottomButtonStyle == QUIT_APP_TEXT) { + // if action button and QUIT_APP_TEXT bottom button, use a pair of choice buttons + if ((info->actionButtonText != NULL)) { + nbgl_layoutChoiceButtons_t buttonsInfo = {.topText = info->actionButtonText, + .bottomText = "Quit app", + .token = info->bottomButtonsToken, + .style = BOTH_ROUNDED_STYLE, + .tuneId = info->tuneId}; + nbgl_layoutAddChoiceButtons(layout, &buttonsInfo); + } + else { + nbgl_layoutButton_t buttonInfo = {.fittingContent = false, + .icon = NULL, + .onBottom = true, + .style = WHITE_BACKGROUND, + .text = "Quit app", + .token = info->bottomButtonsToken, + .tuneId = info->tuneId}; + nbgl_layoutAddButton(layout, &buttonInfo); + } + } + else if (info->bottomButtonStyle != NO_BUTTON_STYLE) { + const nbgl_icon_details_t *icon; + if (info->bottomButtonStyle == SETTINGS_ICON) { + icon = &C_wheel32px; + } + else if (info->bottomButtonStyle == INFO_ICON) { + icon = &C_info_i_32px; + } + else if (info->bottomButtonStyle == QUIT_ICON) { + icon = &C_cross32px; + } + else { + return NULL; + } + nbgl_layoutAddBottomButton( + layout, PIC(icon), info->bottomButtonsToken, false, info->tuneId); + } + nbgl_layoutDraw(layout); + + return (nbgl_page_t *) layout; } /** - * @brief draw a confirmation page, with a centered info (icon and/or text), a button to confirm and a footer to cancel + * @brief draw a confirmation page, with a centered info (icon and/or text), a button to confirm and + * a footer to cancel * * @param onActionCallback common callback for all actions on this page * @param info structure describing the centered info and other controls of this page * @return the page context (or NULL if error) */ -nbgl_page_t* nbgl_pageDrawConfirmation(nbgl_layoutTouchCallback_t onActionCallback, const nbgl_pageConfirmationDescription_t *info) { - nbgl_layoutDescription_t layoutDescription; - nbgl_layout_t *layout; - - layoutDescription.modal = info->modal; - layoutDescription.withLeftBorder = true; - - layoutDescription.onActionCallback = onActionCallback; - layoutDescription.tapActionText = NULL; - - layoutDescription.ticker.tickerCallback = NULL; - layout = nbgl_layoutGet(&layoutDescription); - if (info->cancelText == NULL) { - nbgl_layoutButton_t buttonInfo = { - .style = BLACK_BACKGROUND, - .text = info->confirmationText, - .icon = NULL, - .token = info->confirmationToken, - .fittingContent = false, - .tuneId = info->tuneId, - .onBottom = true - }; - nbgl_layoutAddBottomButton(layout, PIC(&C_cross32px), info->cancelToken, true, info->tuneId); - nbgl_layoutAddButton(layout, &buttonInfo); - } - else { - nbgl_layoutChoiceButtons_t buttonsInfo = { - .bottomText = PIC(info->cancelText), - .token = info->confirmationToken, - .topText = PIC(info->confirmationText), - .style = ROUNDED_AND_FOOTER_STYLE, - .tuneId = info->tuneId - }; - nbgl_layoutAddChoiceButtons(layout,&buttonsInfo); - } - nbgl_layoutAddCenteredInfo(layout,&info->centeredInfo); - - nbgl_layoutDraw(layout); - - return (nbgl_page_t*)layout; -} +nbgl_page_t *nbgl_pageDrawConfirmation(nbgl_layoutTouchCallback_t onActionCallback, + const nbgl_pageConfirmationDescription_t *info) +{ + nbgl_layoutDescription_t layoutDescription; + nbgl_layout_t *layout; + + layoutDescription.modal = info->modal; + layoutDescription.withLeftBorder = true; + + layoutDescription.onActionCallback = onActionCallback; + layoutDescription.tapActionText = NULL; + + layoutDescription.ticker.tickerCallback = NULL; + layout = nbgl_layoutGet(&layoutDescription); + if (info->cancelText == NULL) { + nbgl_layoutButton_t buttonInfo = {.style = BLACK_BACKGROUND, + .text = info->confirmationText, + .icon = NULL, + .token = info->confirmationToken, + .fittingContent = false, + .tuneId = info->tuneId, + .onBottom = true}; + nbgl_layoutAddBottomButton( + layout, PIC(&C_cross32px), info->cancelToken, true, info->tuneId); + nbgl_layoutAddButton(layout, &buttonInfo); + } + else { + nbgl_layoutChoiceButtons_t buttonsInfo = {.bottomText = PIC(info->cancelText), + .token = info->confirmationToken, + .topText = PIC(info->confirmationText), + .style = ROUNDED_AND_FOOTER_STYLE, + .tuneId = info->tuneId}; + nbgl_layoutAddChoiceButtons(layout, &buttonsInfo); + } + nbgl_layoutAddCenteredInfo(layout, &info->centeredInfo); + nbgl_layoutDraw(layout); + + return (nbgl_page_t *) layout; +} /** - * @brief draw a generic content page, with the given content, and if nav parameter is not NULL, with the given - * navigation controls (either with navigation bar or with "tap" and "back") + * @brief draw a generic content page, with the given content, and if nav parameter is not NULL, + * with the given navigation controls (either with navigation bar or with "tap" and "back") * * @param onActionCallback common callback for all actions on this page * @param nav structure describing the navigation controls of this page (no navigation if NULL) @@ -415,70 +425,85 @@ nbgl_page_t* nbgl_pageDrawConfirmation(nbgl_layoutTouchCallback_t onActionCallba * @param modal set to true to draw as a modal * @return the page context (or NULL if error) */ -nbgl_page_t* nbgl_pageDrawGenericContentExt(nbgl_layoutTouchCallback_t onActionCallback, +nbgl_page_t *nbgl_pageDrawGenericContentExt(nbgl_layoutTouchCallback_t onActionCallback, const nbgl_pageNavigationInfo_t *nav, - nbgl_pageContent_t* content, - bool modal) { - nbgl_layoutDescription_t layoutDescription; - nbgl_layout_t *layout; - - layoutDescription.modal = modal; - layoutDescription.withLeftBorder = true; - layoutDescription.onActionCallback = onActionCallback; - layoutDescription.ticker.tickerCallback = NULL; - - if ((nav != NULL) && (nav->navType == NAV_WITH_TAP)) { - layoutDescription.tapActionText = nav->navWithTap.nextPageText; - layoutDescription.tapActionToken = nav->navWithTap.nextPageToken; - layoutDescription.tapTuneId = nav->tuneId; - } - else { - layoutDescription.tapActionText = NULL; - } - - layout = nbgl_layoutGet(&layoutDescription); - if (nav != NULL) { - if (nav->navType == NAV_WITH_TAP) { - if (nav->navWithTap.skipText == NULL) - nbgl_layoutAddFooter(layout, nav->navWithTap.quitText, nav->quitToken, nav->tuneId); - else - nbgl_layoutAddSplitFooter(layout, nav->navWithTap.quitText, nav->quitToken, nav->navWithTap.skipText, nav->navWithTap.skipToken, nav->tuneId); - if (nav->progressIndicator) - nbgl_layoutAddProgressIndicator(layout, nav->activePage, nav->nbPages, nav->navWithTap.backButton, nav->navWithTap.backToken, nav->tuneId); + nbgl_pageContent_t *content, + bool modal) +{ + nbgl_layoutDescription_t layoutDescription; + nbgl_layout_t *layout; + + layoutDescription.modal = modal; + layoutDescription.withLeftBorder = true; + layoutDescription.onActionCallback = onActionCallback; + layoutDescription.ticker.tickerCallback = NULL; + + if ((nav != NULL) && (nav->navType == NAV_WITH_TAP)) { + layoutDescription.tapActionText = nav->navWithTap.nextPageText; + layoutDescription.tapActionToken = nav->navWithTap.nextPageToken; + layoutDescription.tapTuneId = nav->tuneId; } - else if (nav->navType == NAV_WITH_BUTTONS) { - nbgl_layoutNavigationBar_t navInfo = { - .activePage = nav->activePage, - .nbPages = nav->nbPages, - .token = nav->navWithButtons.navToken, - .withExitKey = nav->navWithButtons.quitButton, - .withSeparationLine = true, - .tuneId = nav->tuneId - }; - nbgl_layoutAddNavigationBar(layout,&navInfo); - if (nav->progressIndicator) - nbgl_layoutAddProgressIndicator(layout, nav->activePage, nav->nbPages, false, 0, nav->tuneId); + else { + layoutDescription.tapActionText = NULL; + } + + layout = nbgl_layoutGet(&layoutDescription); + if (nav != NULL) { + if (nav->navType == NAV_WITH_TAP) { + if (nav->navWithTap.skipText == NULL) { + nbgl_layoutAddFooter(layout, nav->navWithTap.quitText, nav->quitToken, nav->tuneId); + } + else { + nbgl_layoutAddSplitFooter(layout, + nav->navWithTap.quitText, + nav->quitToken, + nav->navWithTap.skipText, + nav->navWithTap.skipToken, + nav->tuneId); + } + if (nav->progressIndicator) { + nbgl_layoutAddProgressIndicator(layout, + nav->activePage, + nav->nbPages, + nav->navWithTap.backButton, + nav->navWithTap.backToken, + nav->tuneId); + } + } + else if (nav->navType == NAV_WITH_BUTTONS) { + nbgl_layoutNavigationBar_t navInfo = {.activePage = nav->activePage, + .nbPages = nav->nbPages, + .token = nav->navWithButtons.navToken, + .withExitKey = nav->navWithButtons.quitButton, + .withSeparationLine = true, + .tuneId = nav->tuneId}; + nbgl_layoutAddNavigationBar(layout, &navInfo); + if (nav->progressIndicator) { + nbgl_layoutAddProgressIndicator( + layout, nav->activePage, nav->nbPages, false, 0, nav->tuneId); + } + } } - } - addContent(content, layout); - nbgl_layoutDraw(layout); + addContent(content, layout); + nbgl_layoutDraw(layout); - return (nbgl_page_t*)layout; + return (nbgl_page_t *) layout; } /** - * @brief draw a generic content page, with the given content, and if nav parameter is not NULL, with the given - * navigation controls (either with navigation bar or with "tap" and "back") + * @brief draw a generic content page, with the given content, and if nav parameter is not NULL, + * with the given navigation controls (either with navigation bar or with "tap" and "back") * * @param onActionCallback common callback for all actions on this page * @param nav structure describing the navigation controls of this page (no navigation if NULL) * @param content structure describing the main content of this page * @return the page context (or NULL if error) */ -nbgl_page_t* nbgl_pageDrawGenericContent(nbgl_layoutTouchCallback_t onActionCallback, +nbgl_page_t *nbgl_pageDrawGenericContent(nbgl_layoutTouchCallback_t onActionCallback, const nbgl_pageNavigationInfo_t *nav, - nbgl_pageContent_t* content) { - return nbgl_pageDrawGenericContentExt(onActionCallback,nav,content,false); + nbgl_pageContent_t *content) +{ + return nbgl_pageDrawGenericContentExt(onActionCallback, nav, content, false); } /** @@ -487,12 +512,13 @@ nbgl_page_t* nbgl_pageDrawGenericContent(nbgl_layoutTouchCallback_t onActionCall * @param page page to release * @return >= 0 if OK */ -int nbgl_pageRelease(nbgl_page_t* page) { - int ret; +int nbgl_pageRelease(nbgl_page_t *page) +{ + int ret; - LOG_DEBUG(PAGE_LOGGER,"nbgl_pageRelease(): \n"); - ret = nbgl_layoutRelease((nbgl_layout_t *)page); + LOG_DEBUG(PAGE_LOGGER, "nbgl_pageRelease(): \n"); + ret = nbgl_layoutRelease((nbgl_layout_t *) page); - return ret; + return ret; } -#endif // NBGL_PAGE +#endif // NBGL_PAGE diff --git a/lib_nbgl/src/nbgl_screen.c b/lib_nbgl/src/nbgl_screen.c index e04bcf842..68eda239a 100644 --- a/lib_nbgl/src/nbgl_screen.c +++ b/lib_nbgl/src/nbgl_screen.c @@ -59,274 +59,311 @@ static nbgl_screen_t *topOfStack; * @brief This function redraws the whole screen on top of stack and its children * */ -void nbgl_screenRedraw(void) { - if (nbScreensOnStack == 0) { - LOG_WARN(SCREEN_LOGGER,"nbgl_screenRedraw(): no screen to redraw\n"); - return; - } - LOG_DEBUG(SCREEN_LOGGER,"nbgl_screenRedraw(): nbScreensOnStack = %d\n",nbScreensOnStack); +void nbgl_screenRedraw(void) +{ + if (nbScreensOnStack == 0) { + LOG_WARN(SCREEN_LOGGER, "nbgl_screenRedraw(): no screen to redraw\n"); + return; + } + LOG_DEBUG(SCREEN_LOGGER, "nbgl_screenRedraw(): nbScreensOnStack = %d\n", nbScreensOnStack); #ifdef HAVE_SE_TOUCH - // by default, exclude left & top borders from touch - // if any sub-object is a keyboard, this will be modified when drawing it - touch_exclude_borders(TOP_BORDER | LEFT_BORDER); -#endif // HAVE_SE_TOUCH + // by default, exclude left & top borders from touch + // if any sub-object is a keyboard, this will be modified when drawing it + touch_exclude_borders(TOP_BORDER | LEFT_BORDER); +#endif // HAVE_SE_TOUCH - nbgl_screen_reinit(); - nbgl_redrawObject((nbgl_obj_t *)topOfStack, NULL, true); + nbgl_screen_reinit(); + nbgl_redrawObject((nbgl_obj_t *) topOfStack, NULL, true); } /** * @brief Returns the screen on top layer, as a generic object * @return the screen on top layer, or NULL if no screen in stack */ -nbgl_obj_t *nbgl_screenGetTop(void) { - if (nbScreensOnStack > 0) - return (nbgl_obj_t *)topOfStack; - else - return NULL; +nbgl_obj_t *nbgl_screenGetTop(void) +{ + if (nbScreensOnStack > 0) { + return (nbgl_obj_t *) topOfStack; + } + else { + return NULL; + } } /** * @brief Returns the number of used screens on stack * @return the number of used screens on stack */ -uint8_t nbgl_screenGetCurrentStackSize(void) { - if ((nbScreensOnStack == 1) && (screenStack[0].container.nbChildren == 0)) - return 0; - return nbScreensOnStack; +uint8_t nbgl_screenGetCurrentStackSize(void) +{ + if ((nbScreensOnStack == 1) && (screenStack[0].container.nbChildren == 0)) { + return 0; + } + return nbScreensOnStack; } /** * @brief Set the children of the screen with the given array of nbgl_obj_t* * It will replace the current children array. - * A @ref nbgl_screenRedraw() can be called after that to draw all the given objects (and their children) + * A @ref nbgl_screenRedraw() can be called after that to draw all the given objects (and their + * children) * - * @param screenIndex index of the screen in the stack. 0 is the usual value, except for modal windows + * @param screenIndex index of the screen in the stack. 0 is the usual value, except for modal + * windows * @param children an array of nbgl_obj_t* * @param nbChildren number of elements in children array * @param ticker configuration of ticker - * @param callback callback called when any touchable object of the screen is touched (except keyboard/keypad) + * @param callback callback called when any touchable object of the screen is touched (except + * keyboard/keypad) * * @return >= 0 if OK */ -static int nbgl_screenSetAt(uint8_t screenIndex, nbgl_obj_t*** children, uint8_t nbChildren, +static int nbgl_screenSetAt(uint8_t screenIndex, + nbgl_obj_t ***children, + uint8_t nbChildren, const nbgl_screenTickerConfiguration_t *ticker, - nbgl_touchCallback_t callback) { - if (screenIndex >= SCREEN_STACK_SIZE) { - LOG_WARN(SCREEN_LOGGER,"nbgl_screenSetAt(): forbidden screenIndex (%d)\n",screenIndex); - return -1; - } - *children = nbgl_containerPoolGet(nbChildren,screenIndex); - screenStack[screenIndex].container.obj.type = SCREEN; - screenStack[screenIndex].container.obj.area.backgroundColor = WHITE; - screenStack[screenIndex].container.obj.area.height = SCREEN_HEIGHT; - screenStack[screenIndex].container.obj.area.width = SCREEN_WIDTH; - screenStack[screenIndex].container.obj.area.x0 = 0; - screenStack[screenIndex].container.obj.area.y0 = 0; - screenStack[screenIndex].container.obj.rel_x0 = 0; - screenStack[screenIndex].container.obj.rel_y0 = 0; - screenStack[screenIndex].container.layout = VERTICAL; - screenStack[screenIndex].container.children = *children; - screenStack[screenIndex].container.nbChildren = nbChildren; - screenStack[screenIndex].touchCallback = callback; - if (ticker != NULL) { - screenStack[screenIndex].ticker.tickerCallback = (nbgl_tickerCallback_t)PIC(ticker->tickerCallback); - screenStack[screenIndex].ticker.tickerIntervale = ticker->tickerIntervale; - screenStack[screenIndex].ticker.tickerValue = ticker->tickerValue; - } - else { - screenStack[screenIndex].ticker.tickerCallback = NULL; - } - return 0; + nbgl_touchCallback_t callback) +{ + if (screenIndex >= SCREEN_STACK_SIZE) { + LOG_WARN(SCREEN_LOGGER, "nbgl_screenSetAt(): forbidden screenIndex (%d)\n", screenIndex); + return -1; + } + *children = nbgl_containerPoolGet(nbChildren, screenIndex); + screenStack[screenIndex].container.obj.type = SCREEN; + screenStack[screenIndex].container.obj.area.backgroundColor = WHITE; + screenStack[screenIndex].container.obj.area.height = SCREEN_HEIGHT; + screenStack[screenIndex].container.obj.area.width = SCREEN_WIDTH; + screenStack[screenIndex].container.obj.area.x0 = 0; + screenStack[screenIndex].container.obj.area.y0 = 0; + screenStack[screenIndex].container.obj.rel_x0 = 0; + screenStack[screenIndex].container.obj.rel_y0 = 0; + screenStack[screenIndex].container.layout = VERTICAL; + screenStack[screenIndex].container.children = *children; + screenStack[screenIndex].container.nbChildren = nbChildren; + screenStack[screenIndex].touchCallback = callback; + if (ticker != NULL) { + screenStack[screenIndex].ticker.tickerCallback + = (nbgl_tickerCallback_t) PIC(ticker->tickerCallback); + screenStack[screenIndex].ticker.tickerIntervale = ticker->tickerIntervale; + screenStack[screenIndex].ticker.tickerValue = ticker->tickerValue; + } + else { + screenStack[screenIndex].ticker.tickerCallback = NULL; + } + return 0; } /** * @brief Configures the lowest layer screen. To be used by applications - * A @ref nbgl_screenRedraw() can be called after that to draw all the given objects (and their children) + * A @ref nbgl_screenRedraw() can be called after that to draw all the given objects (and their + * children) * - * @param elements an pointer on an array of nbgl_obj_t* to get as children of the screen, it will be allocated by the function + * @param elements an pointer on an array of nbgl_obj_t* to get as children of the screen, it will + * be allocated by the function * @param nbElements number of elements in elements array * @param ticker if not NULL, configures the potential ticker to be used as a periodic timer - * @param callback callback called when any touchable object of the screen is touched (except keyboard/keypad) (can be NULL) + * @param callback callback called when any touchable object of the screen is touched (except + * keyboard/keypad) (can be NULL) * * @return >= 0 if OK */ -int nbgl_screenSet(nbgl_obj_t*** elements, uint8_t nbElements, +int nbgl_screenSet(nbgl_obj_t ***elements, + uint8_t nbElements, const nbgl_screenTickerConfiguration_t *ticker, - nbgl_touchCallback_t callback) { - // if no screen, consider it as a first fake push - if (nbScreensOnStack == 0) { - nbScreensOnStack++; - topOfStack = &screenStack[0]; - } - // release used objects and containers - nbgl_objPoolRelease(0); - nbgl_containerPoolRelease(0); - // always use the first layer (background) for user application - return nbgl_screenSetAt(0, elements, nbElements, ticker, callback); + nbgl_touchCallback_t callback) +{ + // if no screen, consider it as a first fake push + if (nbScreensOnStack == 0) { + nbScreensOnStack++; + topOfStack = &screenStack[0]; + } + // release used objects and containers + nbgl_objPoolRelease(0); + nbgl_containerPoolRelease(0); + // always use the first layer (background) for user application + return nbgl_screenSetAt(0, elements, nbElements, ticker, callback); } /** - * @brief Updates the number of children on given layer. can only be smaller than the number given in @ref nbgl_screenSet() + * @brief Updates the number of children on given layer. can only be smaller than the number given + * in @ref nbgl_screenSet() * - * @param screenIndex index of the screen in the stack. 0 is the usual value, except for modal windows + * @param screenIndex index of the screen in the stack. 0 is the usual value, except for modal + * windows * @param nbElements number of elements in elements array * * @return >= 0 if OK */ -int nbgl_screenUpdateNbElements(uint8_t screenIndex, uint8_t nbElements) { - screenStack[screenIndex].container.nbChildren = nbElements; - return 0; +int nbgl_screenUpdateNbElements(uint8_t screenIndex, uint8_t nbElements) +{ + screenStack[screenIndex].container.nbChildren = nbElements; + return 0; } /** - * @brief Updates the background color of the screen at the given screenIndex, always set at @ref WHITE in + * @brief Updates the background color of the screen at the given screenIndex, always set at @ref + * WHITE in * - * @param screenIndex index of the screen in the stack. 0 is the usual value, except for modal windows + * @param screenIndex index of the screen in the stack. 0 is the usual value, except for modal + * windows * @param color color to set as background color for tge screen * * @return >= 0 if OK */ -int nbgl_screenUpdateBackgroundColor(uint8_t screenIndex, color_t color) { - screenStack[screenIndex].container.obj.area.backgroundColor = color; - return 0; +int nbgl_screenUpdateBackgroundColor(uint8_t screenIndex, color_t color) +{ + screenStack[screenIndex].container.obj.area.backgroundColor = color; + return 0; } /** - * @brief Updates the ticker configuration of the screen at the given screenIndex, always set at @ref WHITE in + * @brief Updates the ticker configuration of the screen at the given screenIndex, always set at + * @ref WHITE in * - * @param screenIndex index of the screen in the stack. 0 is the usual value, except for modal windows + * @param screenIndex index of the screen in the stack. 0 is the usual value, except for modal + * windows * @param ticker if not NULL, configures the potential ticker to be used as a periodic timer * * @return >= 0 if OK */ -int nbgl_screenUpdateTicker(uint8_t screenIndex, const nbgl_screenTickerConfiguration_t *ticker) { - if (ticker != NULL) { - screenStack[screenIndex].ticker.tickerCallback = (nbgl_tickerCallback_t)PIC(ticker->tickerCallback); - screenStack[screenIndex].ticker.tickerIntervale = ticker->tickerIntervale; - screenStack[screenIndex].ticker.tickerValue = ticker->tickerValue; - } - else { - screenStack[screenIndex].ticker.tickerCallback = NULL; - } - return 0; +int nbgl_screenUpdateTicker(uint8_t screenIndex, const nbgl_screenTickerConfiguration_t *ticker) +{ + if (ticker != NULL) { + screenStack[screenIndex].ticker.tickerCallback + = (nbgl_tickerCallback_t) PIC(ticker->tickerCallback); + screenStack[screenIndex].ticker.tickerIntervale = ticker->tickerIntervale; + screenStack[screenIndex].ticker.tickerValue = ticker->tickerValue; + } + else { + screenStack[screenIndex].ticker.tickerCallback = NULL; + } + return 0; } /** - * @brief Returns the array of elements (children) of the screen at the given index (return value of @ref nbgl_screenPush() or 0 - * for a screen created with @ref nbgl_screenSet()) + * @brief Returns the array of elements (children) of the screen at the given index (return value of + * @ref nbgl_screenPush() or 0 for a screen created with @ref nbgl_screenSet()) + * + * @param screenIndex index of the screen in the stack. 0 is the usual value, except for modal + * windows * - * @param screenIndex index of the screen in the stack. 0 is the usual value, except for modal windows - * * @return array of elements (children) of the screen */ -nbgl_obj_t** nbgl_screenGetElements(uint8_t screenIndex) { - return screenStack[screenIndex].container.children; +nbgl_obj_t **nbgl_screenGetElements(uint8_t screenIndex) +{ + return screenStack[screenIndex].container.children; } /** - * @brief Pushes a screen on top of the stack, with the given number of elements, if possible. The array of children for - * this screen is set in given elements parameter - * A @ref nbgl_screenRedraw() can be called after that to draw all the given objects (and their children) + * @brief Pushes a screen on top of the stack, with the given number of elements, if possible. The + * array of children for this screen is set in given elements parameter A @ref + * nbgl_screenRedraw() can be called after that to draw all the given objects (and their children) * * @param elements (output) an array of nbgl_obj_t** to get * @param nbElements number of elements to get in elements array * @param ticker if not NULL, configures the potential ticker to be used as a periodic timer - * @param callback callback called when any touchable object of the screen is touched (except keyboard/keypad) (can be NULL) + * @param callback callback called when any touchable object of the screen is touched (except + * keyboard/keypad) (can be NULL) * * @return current screen index, or < 0 if error */ -int nbgl_screenPush(nbgl_obj_t*** elements, uint8_t nbElements, +int nbgl_screenPush(nbgl_obj_t ***elements, + uint8_t nbElements, const nbgl_screenTickerConfiguration_t *ticker, - nbgl_touchCallback_t callback) { - uint8_t screenIndex; - if (nbScreensOnStack >= SCREEN_STACK_SIZE) { - LOG_WARN(SCREEN_LOGGER,"nbgl_screenPush(): already in highest index in the stack(%d)\n",nbScreensOnStack-1); - return -1; - } - // if no screen, consider it as a first fake push - if (nbScreensOnStack == 0) { - screenIndex = 1; // push at position 1 because 0 is reserved for background - topOfStack = &screenStack[screenIndex]; - topOfStack->next = NULL; - // link top of stack to background (even if empty) - topOfStack->previous = &screenStack[0]; - screenStack[0].next = topOfStack; - screenStack[0].container.nbChildren = 0; - // count empty background as an active screen - nbScreensOnStack++; - } - else { - // find a non used screen in the array - for (screenIndex=1;screenIndexnext = &screenStack[screenIndex]; - screenStack[screenIndex].previous = topOfStack; - // new top of stack - topOfStack = &screenStack[screenIndex]; + nbgl_touchCallback_t callback) +{ + uint8_t screenIndex; + if (nbScreensOnStack >= SCREEN_STACK_SIZE) { + LOG_WARN(SCREEN_LOGGER, + "nbgl_screenPush(): already in highest index in the stack(%d)\n", + nbScreensOnStack - 1); + return -1; + } + // if no screen, consider it as a first fake push + if (nbScreensOnStack == 0) { + screenIndex = 1; // push at position 1 because 0 is reserved for background + topOfStack = &screenStack[screenIndex]; topOfStack->next = NULL; - break; - } + // link top of stack to background (even if empty) + topOfStack->previous = &screenStack[0]; + screenStack[0].next = topOfStack; + screenStack[0].container.nbChildren = 0; + // count empty background as an active screen + nbScreensOnStack++; + } + else { + // find a non used screen in the array + for (screenIndex = 1; screenIndex < SCREEN_STACK_SIZE; screenIndex++) { + if (screenStack[screenIndex].previous == NULL) { + // if no previous, means unused, so take it + // update previous topOfStack + topOfStack->next = &screenStack[screenIndex]; + screenStack[screenIndex].previous = topOfStack; + // new top of stack + topOfStack = &screenStack[screenIndex]; + topOfStack->next = NULL; + break; + } + } + if (screenIndex == SCREEN_STACK_SIZE) { + // should never happen + LOG_WARN(SCREEN_LOGGER, "nbgl_screenPush(): corruption in stack\n"); + } } - if (screenIndex == SCREEN_STACK_SIZE) { - // should never happen - LOG_WARN(SCREEN_LOGGER,"nbgl_screenPush(): corruption in stack\n"); + if (nbgl_screenSetAt(screenIndex, elements, nbElements, ticker, callback) >= 0) { + nbScreensOnStack++; + LOG_DEBUG(SCREEN_LOGGER, "nbgl_screenPush(): screen %d is now top of stack\n", screenIndex); + return screenIndex; + } + else { + return -1; } - } - if (nbgl_screenSetAt(screenIndex, elements, nbElements, ticker, callback) >= 0) { - nbScreensOnStack++; - LOG_DEBUG(SCREEN_LOGGER,"nbgl_screenPush(): screen %d is now top of stack\n",screenIndex); - return screenIndex; - } - else { - return -1; - } } /** - * @brief Release the screen at the given index in screen array (index returned by @ref nbgl_screenPush()). - * A @ref nbgl_screenRedraw() can be called after that to draw all objects in the new top of the stack + * @brief Release the screen at the given index in screen array (index returned by @ref + * nbgl_screenPush()). A @ref nbgl_screenRedraw() can be called after that to draw all objects in + * the new top of the stack * - * @param screenIndex index of the screen to pop in the stack. 0 is the usual value, except for modal windows + * @param screenIndex index of the screen to pop in the stack. 0 is the usual value, except for + * modal windows * @return the index of screen on top of stack (if -1, the stack is empty) */ -int nbgl_screenPop(uint8_t screenIndex) { - if (nbScreensOnStack == 0) { - LOG_WARN(SCREEN_LOGGER,"nbgl_screenPop(): already in lowest index in the stack\n"); - return -1; - } - LOG_DEBUG(SCREEN_LOGGER,"nbgl_screenPop(): at index %d\n",screenIndex); - nbScreensOnStack--; - // move top of stack if needed - if (&screenStack[screenIndex] == topOfStack) { +int nbgl_screenPop(uint8_t screenIndex) +{ if (nbScreensOnStack == 0) { - topOfStack = NULL; - } - else { - topOfStack = topOfStack->previous; + LOG_WARN(SCREEN_LOGGER, "nbgl_screenPop(): already in lowest index in the stack\n"); + return -1; } - } - else { - // connect previous to next - if (screenStack[screenIndex].previous != NULL) { - screenStack[screenIndex].previous->next = screenStack[screenIndex].next; + LOG_DEBUG(SCREEN_LOGGER, "nbgl_screenPop(): at index %d\n", screenIndex); + nbScreensOnStack--; + // move top of stack if needed + if (&screenStack[screenIndex] == topOfStack) { + if (nbScreensOnStack == 0) { + topOfStack = NULL; + } + else { + topOfStack = topOfStack->previous; + } } - if (screenStack[screenIndex].next != NULL) { - screenStack[screenIndex].next->previous = screenStack[screenIndex].previous; + else { + // connect previous to next + if (screenStack[screenIndex].previous != NULL) { + screenStack[screenIndex].previous->next = screenStack[screenIndex].next; + } + if (screenStack[screenIndex].next != NULL) { + screenStack[screenIndex].next->previous = screenStack[screenIndex].previous; + } } - } - // free slot - screenStack[screenIndex].previous = NULL; - screenStack[screenIndex].next = NULL; - screenStack[screenIndex].container.nbChildren = 0; - screenStack[screenIndex].container.children = NULL; - // release used objects and containers - nbgl_objPoolRelease(screenIndex); - nbgl_containerPoolRelease(screenIndex); - return 0; + // free slot + screenStack[screenIndex].previous = NULL; + screenStack[screenIndex].next = NULL; + screenStack[screenIndex].container.nbChildren = 0; + screenStack[screenIndex].container.children = NULL; + // release used objects and containers + nbgl_objPoolRelease(screenIndex); + nbgl_containerPoolRelease(screenIndex); + return 0; } /** @@ -335,18 +372,20 @@ int nbgl_screenPop(uint8_t screenIndex) { * * @return >= 0 if OK */ -int nbgl_screenReset(void) { - uint8_t screenIndex; - for (screenIndex=0;screenIndexticker.tickerCallback != NULL) && - (topOfStack->ticker.tickerValue != 0)) { - topOfStack->ticker.tickerValue -= MIN(topOfStack->ticker.tickerValue, intervaleMs); - if (topOfStack->ticker.tickerValue == 0) { - // rearm if intervale is not null, and call the registered function - topOfStack->ticker.tickerValue = topOfStack->ticker.tickerIntervale; - topOfStack->ticker.tickerCallback(); +void nbgl_screenHandler(uint32_t intervaleMs) +{ + // ensure a screen exists + if (nbScreensOnStack == 0) { + return; + } + // call ticker callback of top of stack if active and not expired yet (for a non periodic) + if ((topOfStack->ticker.tickerCallback != NULL) && (topOfStack->ticker.tickerValue != 0)) { + topOfStack->ticker.tickerValue -= MIN(topOfStack->ticker.tickerValue, intervaleMs); + if (topOfStack->ticker.tickerValue == 0) { + // rearm if intervale is not null, and call the registered function + topOfStack->ticker.tickerValue = topOfStack->ticker.tickerIntervale; + topOfStack->ticker.tickerCallback(); + } } - } } /** @@ -377,33 +417,33 @@ void nbgl_screenHandler(uint32_t intervaleMs) { * @param obj the object to search * @return true if belongs, false otherwise */ -static bool objIsIn(nbgl_obj_t *refObj, nbgl_obj_t *obj) { - uint8_t i; +static bool objIsIn(nbgl_obj_t *refObj, nbgl_obj_t *obj) +{ + uint8_t i; - if (obj == NULL) { - return false; - } - if ((nbgl_obj_t *)refObj == obj) { - LOG_DEBUG(SCREEN_LOGGER,"nbgl_screenContainsObj(): yes\n"); - return true; - } + if (obj == NULL) { + return false; + } + if ((nbgl_obj_t *) refObj == obj) { + LOG_DEBUG(SCREEN_LOGGER, "nbgl_screenContainsObj(): yes\n"); + return true; + } - if ((refObj->type == SCREEN) || - (refObj->type == CONTAINER)) { - nbgl_container_t *container = (nbgl_container_t *)refObj; - // draw the children, if any - if (container->children != NULL) { - for (i=0;inbChildren;i++) { - nbgl_obj_t *current = container->children[i]; - if (current != NULL) { - if (objIsIn(current,obj) == true) { - return true; - } + if ((refObj->type == SCREEN) || (refObj->type == CONTAINER)) { + nbgl_container_t *container = (nbgl_container_t *) refObj; + // draw the children, if any + if (container->children != NULL) { + for (i = 0; i < container->nbChildren; i++) { + nbgl_obj_t *current = container->children[i]; + if (current != NULL) { + if (objIsIn(current, obj) == true) { + return true; + } + } + } } - } } - } - return false; + return false; } /** @@ -412,8 +452,10 @@ static bool objIsIn(nbgl_obj_t *refObj, nbgl_obj_t *obj) { * @param obj the object to search * @return true if belongs, false otherwise */ -bool nbgl_screenContainsObj(nbgl_obj_t *obj) { - if (nbScreensOnStack == 0) - return false; - return objIsIn((nbgl_obj_t *)topOfStack,obj); +bool nbgl_screenContainsObj(nbgl_obj_t *obj) +{ + if (nbScreensOnStack == 0) { + return false; + } + return objIsIn((nbgl_obj_t *) topOfStack, obj); } diff --git a/lib_nbgl/src/nbgl_serialize.c b/lib_nbgl/src/nbgl_serialize.c index 8e99551a1..85c1acc65 100644 --- a/lib_nbgl/src/nbgl_serialize.c +++ b/lib_nbgl/src/nbgl_serialize.c @@ -3,269 +3,306 @@ // Utility functions -static void nbgl_appendU8(uint8_t value, uint8_t *out, size_t *w_cnt, size_t max_len) { - if(*w_cnt < max_len) { - out[*w_cnt] = value; - (*w_cnt)++; - } +static void nbgl_appendU8(uint8_t value, uint8_t *out, size_t *w_cnt, size_t max_len) +{ + if (*w_cnt < max_len) { + out[*w_cnt] = value; + (*w_cnt)++; + } } -static void nbgl_appendU32(uint32_t value, uint8_t *out, size_t *w_cnt, size_t max_len) { - nbgl_appendU8((uint8_t) ((value >> 24) & 0xFF), out, w_cnt, max_len); - nbgl_appendU8((uint8_t) ((value >> 16) & 0xFF), out, w_cnt, max_len); - nbgl_appendU8((uint8_t) ((value >> 8) & 0xFF), out, w_cnt, max_len); - nbgl_appendU8((uint8_t) (value & 0xFF), out, w_cnt, max_len); +static void nbgl_appendU32(uint32_t value, uint8_t *out, size_t *w_cnt, size_t max_len) +{ + nbgl_appendU8((uint8_t) ((value >> 24) & 0xFF), out, w_cnt, max_len); + nbgl_appendU8((uint8_t) ((value >> 16) & 0xFF), out, w_cnt, max_len); + nbgl_appendU8((uint8_t) ((value >> 8) & 0xFF), out, w_cnt, max_len); + nbgl_appendU8((uint8_t) (value & 0xFF), out, w_cnt, max_len); } -static void nbgl_appendU16(uint16_t value, uint8_t *out, size_t *w_cnt, size_t max_len) { - nbgl_appendU8((uint8_t) ((value >> 8) & 0xFF), out, w_cnt, max_len); - nbgl_appendU8((uint8_t) (value & 0xFF), out, w_cnt, max_len); +static void nbgl_appendU16(uint16_t value, uint8_t *out, size_t *w_cnt, size_t max_len) +{ + nbgl_appendU8((uint8_t) ((value >> 8) & 0xFF), out, w_cnt, max_len); + nbgl_appendU8((uint8_t) (value & 0xFF), out, w_cnt, max_len); } -static void nbgl_serializeType(nbgl_obj_t *obj, uint8_t *out, size_t *w_cnt, size_t max_len) { - nbgl_appendU8((uint8_t) obj->type, out, w_cnt, max_len); +static void nbgl_serializeType(nbgl_obj_t *obj, uint8_t *out, size_t *w_cnt, size_t max_len) +{ + nbgl_appendU8((uint8_t) obj->type, out, w_cnt, max_len); } -static void nbgl_serializeArea(nbgl_area_t *area, uint8_t *out, size_t *w_cnt, size_t max_len) { - nbgl_appendU16(area->x0, out, w_cnt, max_len); - nbgl_appendU16(area->y0, out, w_cnt, max_len); - nbgl_appendU16(area->width, out, w_cnt, max_len); - nbgl_appendU16(area->height, out, w_cnt, max_len); - nbgl_appendU8((uint8_t) area->backgroundColor, out, w_cnt, max_len); - nbgl_appendU8((uint8_t) area->bpp, out, w_cnt, max_len); +static void nbgl_serializeArea(nbgl_area_t *area, uint8_t *out, size_t *w_cnt, size_t max_len) +{ + nbgl_appendU16(area->x0, out, w_cnt, max_len); + nbgl_appendU16(area->y0, out, w_cnt, max_len); + nbgl_appendU16(area->width, out, w_cnt, max_len); + nbgl_appendU16(area->height, out, w_cnt, max_len); + nbgl_appendU8((uint8_t) area->backgroundColor, out, w_cnt, max_len); + nbgl_appendU8((uint8_t) area->bpp, out, w_cnt, max_len); } // Serialization functions -static void nbgl_serializeText(const char* text, uint8_t *out, size_t *w_cnt, size_t max_len) { - if (text == NULL) { - nbgl_appendU8('\0', out, w_cnt, max_len); - return; - } else { - while(*w_cnt < max_len) { - nbgl_appendU8(*text, out, w_cnt, max_len); - if(*text == '\0') { - return; - } else { - text++; - } - } - } +static void nbgl_serializeText(const char *text, uint8_t *out, size_t *w_cnt, size_t max_len) +{ + if (text == NULL) { + nbgl_appendU8('\0', out, w_cnt, max_len); + return; + } + else { + while (*w_cnt < max_len) { + nbgl_appendU8(*text, out, w_cnt, max_len); + if (*text == '\0') { + return; + } + else { + text++; + } + } + } } -static void nbgl_serializeTextArea(nbgl_text_area_t *obj, uint8_t *out, size_t *w_cnt, size_t max_len) { - nbgl_serializeType((nbgl_obj_t *) obj, out, w_cnt, max_len); - nbgl_serializeArea((nbgl_area_t *) obj, out, w_cnt, max_len); - - nbgl_appendU8((uint8_t) obj->textColor, out, w_cnt, max_len); - nbgl_appendU8((uint8_t) obj->textAlignment, out, w_cnt, max_len); - nbgl_appendU8((uint8_t) obj->style, out, w_cnt, max_len); - nbgl_appendU8((uint8_t) obj->fontId, out, w_cnt, max_len); - nbgl_appendU8((uint8_t) obj->localized, out, w_cnt, max_len); - nbgl_appendU8((uint8_t) obj->autoHideLongLine, out, w_cnt, max_len); - - nbgl_serializeText(obj->text, out, w_cnt, max_len); +static void nbgl_serializeTextArea(nbgl_text_area_t *obj, + uint8_t *out, + size_t *w_cnt, + size_t max_len) +{ + nbgl_serializeType((nbgl_obj_t *) obj, out, w_cnt, max_len); + nbgl_serializeArea((nbgl_area_t *) obj, out, w_cnt, max_len); + + nbgl_appendU8((uint8_t) obj->textColor, out, w_cnt, max_len); + nbgl_appendU8((uint8_t) obj->textAlignment, out, w_cnt, max_len); + nbgl_appendU8((uint8_t) obj->style, out, w_cnt, max_len); + nbgl_appendU8((uint8_t) obj->fontId, out, w_cnt, max_len); + nbgl_appendU8((uint8_t) obj->localized, out, w_cnt, max_len); + nbgl_appendU8((uint8_t) obj->autoHideLongLine, out, w_cnt, max_len); + + nbgl_serializeText(obj->text, out, w_cnt, max_len); } -static void nbgl_serializeLine(nbgl_line_t *obj, uint8_t *out, size_t *w_cnt, size_t max_len) { - nbgl_serializeType((nbgl_obj_t *) obj, out, w_cnt, max_len); - nbgl_serializeArea((nbgl_area_t *) obj, out, w_cnt, max_len); +static void nbgl_serializeLine(nbgl_line_t *obj, uint8_t *out, size_t *w_cnt, size_t max_len) +{ + nbgl_serializeType((nbgl_obj_t *) obj, out, w_cnt, max_len); + nbgl_serializeArea((nbgl_area_t *) obj, out, w_cnt, max_len); - nbgl_appendU8((uint8_t) obj->direction, out, w_cnt, max_len); - nbgl_appendU8((uint8_t) obj->lineColor, out, w_cnt, max_len); - nbgl_appendU8((uint8_t) obj->thickness, out, w_cnt, max_len); - nbgl_appendU8((uint8_t) obj->offset, out, w_cnt, max_len); + nbgl_appendU8((uint8_t) obj->direction, out, w_cnt, max_len); + nbgl_appendU8((uint8_t) obj->lineColor, out, w_cnt, max_len); + nbgl_appendU8((uint8_t) obj->thickness, out, w_cnt, max_len); + nbgl_appendU8((uint8_t) obj->offset, out, w_cnt, max_len); } -static void nbgl_serializeQrCode(nbgl_qrcode_t *obj, uint8_t *out, size_t *w_cnt, size_t max_len) { - nbgl_serializeType((nbgl_obj_t *) obj, out, w_cnt, max_len); - nbgl_serializeArea((nbgl_area_t *) obj, out, w_cnt, max_len); +static void nbgl_serializeQrCode(nbgl_qrcode_t *obj, uint8_t *out, size_t *w_cnt, size_t max_len) +{ + nbgl_serializeType((nbgl_obj_t *) obj, out, w_cnt, max_len); + nbgl_serializeArea((nbgl_area_t *) obj, out, w_cnt, max_len); - nbgl_appendU8((uint8_t) obj->foregroundColor, out, w_cnt, max_len); - nbgl_appendU8((uint8_t) obj->version, out, w_cnt, max_len); - nbgl_serializeText(obj->text, out, w_cnt, max_len); + nbgl_appendU8((uint8_t) obj->foregroundColor, out, w_cnt, max_len); + nbgl_appendU8((uint8_t) obj->version, out, w_cnt, max_len); + nbgl_serializeText(obj->text, out, w_cnt, max_len); } -static void nbgl_serializeRadio(nbgl_radio_t *obj, uint8_t *out, size_t *w_cnt, size_t max_len) { - nbgl_serializeType((nbgl_obj_t *) obj, out, w_cnt, max_len); - nbgl_serializeArea((nbgl_area_t *) obj, out, w_cnt, max_len); +static void nbgl_serializeRadio(nbgl_radio_t *obj, uint8_t *out, size_t *w_cnt, size_t max_len) +{ + nbgl_serializeType((nbgl_obj_t *) obj, out, w_cnt, max_len); + nbgl_serializeArea((nbgl_area_t *) obj, out, w_cnt, max_len); - nbgl_appendU8((uint8_t) obj->activeColor, out, w_cnt, max_len); - nbgl_appendU8((uint8_t) obj->borderColor, out, w_cnt, max_len); - nbgl_appendU8((uint8_t) obj->state, out, w_cnt, max_len); + nbgl_appendU8((uint8_t) obj->activeColor, out, w_cnt, max_len); + nbgl_appendU8((uint8_t) obj->borderColor, out, w_cnt, max_len); + nbgl_appendU8((uint8_t) obj->state, out, w_cnt, max_len); } -static void nbgl_serializeSwitch(nbgl_switch_t *obj, uint8_t *out, size_t *w_cnt, size_t max_len) { - nbgl_serializeType((nbgl_obj_t *) obj, out, w_cnt, max_len); - nbgl_serializeArea((nbgl_area_t *) obj, out, w_cnt, max_len); +static void nbgl_serializeSwitch(nbgl_switch_t *obj, uint8_t *out, size_t *w_cnt, size_t max_len) +{ + nbgl_serializeType((nbgl_obj_t *) obj, out, w_cnt, max_len); + nbgl_serializeArea((nbgl_area_t *) obj, out, w_cnt, max_len); - nbgl_appendU8((uint8_t) obj->onColor, out, w_cnt, max_len); - nbgl_appendU8((uint8_t) obj->offColor, out, w_cnt, max_len); - nbgl_appendU8((uint8_t) obj->state, out, w_cnt, max_len); + nbgl_appendU8((uint8_t) obj->onColor, out, w_cnt, max_len); + nbgl_appendU8((uint8_t) obj->offColor, out, w_cnt, max_len); + nbgl_appendU8((uint8_t) obj->state, out, w_cnt, max_len); } - static void nbgl_serializeProgressBar(nbgl_progress_bar_t *obj, - uint8_t *out, - size_t *w_cnt, - size_t max_len) { - nbgl_serializeType((nbgl_obj_t *) obj, out, w_cnt, max_len); - nbgl_serializeArea((nbgl_area_t *) obj, out, w_cnt, max_len); - - nbgl_appendU8((uint8_t) obj->withBorder, out, w_cnt, max_len); - nbgl_appendU8((uint8_t) obj->state, out, w_cnt, max_len); + uint8_t *out, + size_t *w_cnt, + size_t max_len) +{ + nbgl_serializeType((nbgl_obj_t *) obj, out, w_cnt, max_len); + nbgl_serializeArea((nbgl_area_t *) obj, out, w_cnt, max_len); + + nbgl_appendU8((uint8_t) obj->withBorder, out, w_cnt, max_len); + nbgl_appendU8((uint8_t) obj->state, out, w_cnt, max_len); } - static void nbgl_serializeNavigationBar(nbgl_page_indicator_t *obj, - uint8_t *out, - size_t *w_cnt, - size_t max_len) { - nbgl_serializeType((nbgl_obj_t *) obj, out, w_cnt, max_len); - nbgl_serializeArea((nbgl_area_t *) obj, out, w_cnt, max_len); - - nbgl_appendU8((uint8_t) obj->activePage, out, w_cnt, max_len); - nbgl_appendU8((uint8_t) obj->nbPages, out, w_cnt, max_len); + uint8_t *out, + size_t *w_cnt, + size_t max_len) +{ + nbgl_serializeType((nbgl_obj_t *) obj, out, w_cnt, max_len); + nbgl_serializeArea((nbgl_area_t *) obj, out, w_cnt, max_len); + + nbgl_appendU8((uint8_t) obj->activePage, out, w_cnt, max_len); + nbgl_appendU8((uint8_t) obj->nbPages, out, w_cnt, max_len); } -static void nbgl_serializeButton(nbgl_button_t *obj, uint8_t *out, size_t *w_cnt, size_t max_len) { - nbgl_serializeType((nbgl_obj_t *) obj, out, w_cnt, max_len); - nbgl_serializeArea((nbgl_area_t *) obj, out, w_cnt, max_len); - - nbgl_appendU8((uint8_t) obj->innerColor, out, w_cnt, max_len); - nbgl_appendU8((uint8_t) obj->borderColor, out, w_cnt, max_len); - nbgl_appendU8((uint8_t) obj->foregroundColor, out, w_cnt, max_len); - nbgl_appendU8((uint8_t) obj->radius, out, w_cnt, max_len); - nbgl_appendU8((uint8_t) obj->fontId, out, w_cnt, max_len); - nbgl_appendU8((uint8_t) obj->localized, out, w_cnt, max_len); - nbgl_serializeText(obj->text, out, w_cnt, max_len); +static void nbgl_serializeButton(nbgl_button_t *obj, uint8_t *out, size_t *w_cnt, size_t max_len) +{ + nbgl_serializeType((nbgl_obj_t *) obj, out, w_cnt, max_len); + nbgl_serializeArea((nbgl_area_t *) obj, out, w_cnt, max_len); + + nbgl_appendU8((uint8_t) obj->innerColor, out, w_cnt, max_len); + nbgl_appendU8((uint8_t) obj->borderColor, out, w_cnt, max_len); + nbgl_appendU8((uint8_t) obj->foregroundColor, out, w_cnt, max_len); + nbgl_appendU8((uint8_t) obj->radius, out, w_cnt, max_len); + nbgl_appendU8((uint8_t) obj->fontId, out, w_cnt, max_len); + nbgl_appendU8((uint8_t) obj->localized, out, w_cnt, max_len); + nbgl_serializeText(obj->text, out, w_cnt, max_len); } -static void nbgl_serializeImage(nbgl_image_t *obj, uint8_t *out, size_t *w_cnt, size_t max_len) { - nbgl_serializeType((nbgl_obj_t *) obj, out, w_cnt, max_len); - nbgl_serializeArea((nbgl_area_t *) obj, out, w_cnt, max_len); +static void nbgl_serializeImage(nbgl_image_t *obj, uint8_t *out, size_t *w_cnt, size_t max_len) +{ + nbgl_serializeType((nbgl_obj_t *) obj, out, w_cnt, max_len); + nbgl_serializeArea((nbgl_area_t *) obj, out, w_cnt, max_len); - nbgl_appendU8((uint8_t) obj->foregroundColor, out, w_cnt, max_len); + nbgl_appendU8((uint8_t) obj->foregroundColor, out, w_cnt, max_len); } -static void nbgl_serializeSpinner(nbgl_spinner_t *obj, uint8_t *out, size_t *w_cnt, size_t max_len) { - nbgl_serializeType((nbgl_obj_t *) obj, out, w_cnt, max_len); - nbgl_serializeArea((nbgl_area_t *) obj, out, w_cnt, max_len); +static void nbgl_serializeSpinner(nbgl_spinner_t *obj, uint8_t *out, size_t *w_cnt, size_t max_len) +{ + nbgl_serializeType((nbgl_obj_t *) obj, out, w_cnt, max_len); + nbgl_serializeArea((nbgl_area_t *) obj, out, w_cnt, max_len); - nbgl_appendU8(obj->position, out, w_cnt, max_len); + nbgl_appendU8(obj->position, out, w_cnt, max_len); } -static void nbgl_serializeKeyboard(nbgl_keyboard_t *obj, uint8_t *out, size_t *w_cnt, size_t max_len) { - nbgl_serializeType((nbgl_obj_t *) obj, out, w_cnt, max_len); - nbgl_serializeArea((nbgl_area_t *) obj, out, w_cnt, max_len); - - nbgl_appendU8((uint8_t) obj->textColor, out, w_cnt, max_len); - nbgl_appendU8((uint8_t) obj->borderColor, out, w_cnt, max_len); - nbgl_appendU8((uint8_t) obj->lettersOnly, out, w_cnt, max_len); - nbgl_appendU8((uint8_t) obj->casing, out, w_cnt, max_len); - nbgl_appendU8((uint8_t) obj->mode, out, w_cnt, max_len); - nbgl_appendU32(obj->keyMask, out, w_cnt, max_len); +static void nbgl_serializeKeyboard(nbgl_keyboard_t *obj, + uint8_t *out, + size_t *w_cnt, + size_t max_len) +{ + nbgl_serializeType((nbgl_obj_t *) obj, out, w_cnt, max_len); + nbgl_serializeArea((nbgl_area_t *) obj, out, w_cnt, max_len); + + nbgl_appendU8((uint8_t) obj->textColor, out, w_cnt, max_len); + nbgl_appendU8((uint8_t) obj->borderColor, out, w_cnt, max_len); + nbgl_appendU8((uint8_t) obj->lettersOnly, out, w_cnt, max_len); + nbgl_appendU8((uint8_t) obj->casing, out, w_cnt, max_len); + nbgl_appendU8((uint8_t) obj->mode, out, w_cnt, max_len); + nbgl_appendU32(obj->keyMask, out, w_cnt, max_len); } -static void nbgl_serializeKeypad(nbgl_keypad_t *obj, uint8_t *out, size_t *w_cnt, size_t max_len) { - nbgl_serializeType((nbgl_obj_t *) obj, out, w_cnt, max_len); - nbgl_serializeArea((nbgl_area_t *) obj, out, w_cnt, max_len); +static void nbgl_serializeKeypad(nbgl_keypad_t *obj, uint8_t *out, size_t *w_cnt, size_t max_len) +{ + nbgl_serializeType((nbgl_obj_t *) obj, out, w_cnt, max_len); + nbgl_serializeArea((nbgl_area_t *) obj, out, w_cnt, max_len); - nbgl_appendU8((uint8_t) obj->textColor, out, w_cnt, max_len); - nbgl_appendU8((uint8_t) obj->borderColor, out, w_cnt, max_len); - nbgl_appendU8((uint8_t) obj->enableBackspace, out, w_cnt, max_len); - nbgl_appendU8((uint8_t) obj->enableValidate, out, w_cnt, max_len); + nbgl_appendU8((uint8_t) obj->textColor, out, w_cnt, max_len); + nbgl_appendU8((uint8_t) obj->borderColor, out, w_cnt, max_len); + nbgl_appendU8((uint8_t) obj->enableBackspace, out, w_cnt, max_len); + nbgl_appendU8((uint8_t) obj->enableValidate, out, w_cnt, max_len); } -static void nbgl_serializeImageFile(nbgl_image_file_t *obj, uint8_t *out, size_t *w_cnt, size_t max_len) { - nbgl_serializeType((nbgl_obj_t *) obj, out, w_cnt, max_len); - nbgl_serializeArea((nbgl_area_t *) obj, out, w_cnt, max_len); +static void nbgl_serializeImageFile(nbgl_image_file_t *obj, + uint8_t *out, + size_t *w_cnt, + size_t max_len) +{ + nbgl_serializeType((nbgl_obj_t *) obj, out, w_cnt, max_len); + nbgl_serializeArea((nbgl_area_t *) obj, out, w_cnt, max_len); } -static void nbgl_serializeContainer(nbgl_container_t *obj, uint8_t *out, size_t *w_cnt, size_t max_len) { - nbgl_serializeType((nbgl_obj_t *) obj, out, w_cnt, max_len); - nbgl_serializeArea((nbgl_area_t *) obj, out, w_cnt, max_len); - - nbgl_appendU8((uint8_t) obj->layout, out, w_cnt, max_len); - nbgl_appendU8((uint8_t) obj->nbChildren, out, w_cnt, max_len); - nbgl_appendU8((uint8_t) obj->forceClean, out, w_cnt, max_len); +static void nbgl_serializeContainer(nbgl_container_t *obj, + uint8_t *out, + size_t *w_cnt, + size_t max_len) +{ + nbgl_serializeType((nbgl_obj_t *) obj, out, w_cnt, max_len); + nbgl_serializeArea((nbgl_area_t *) obj, out, w_cnt, max_len); + + nbgl_appendU8((uint8_t) obj->layout, out, w_cnt, max_len); + nbgl_appendU8((uint8_t) obj->nbChildren, out, w_cnt, max_len); + nbgl_appendU8((uint8_t) obj->forceClean, out, w_cnt, max_len); } -static uint8_t nbgl_serializeObject(nbgl_obj_t *obj, uint8_t *out, size_t *w_cnt, size_t max_len) { - switch(obj->type) { - case SCREEN: - return NBGL_SERIALIZE_ERROR; - case CONTAINER: - nbgl_serializeContainer((nbgl_container_t *) obj, out, w_cnt, max_len); - break; - case IMAGE: - nbgl_serializeImage((nbgl_image_t *) obj, out, w_cnt, max_len); - break; - case LINE: - nbgl_serializeLine((nbgl_line_t *) obj, out, w_cnt, max_len); - break; - case TEXT_AREA: - nbgl_serializeTextArea((nbgl_text_area_t *) obj, out, w_cnt, max_len); - break; - case BUTTON: - nbgl_serializeButton((nbgl_button_t *) obj, out, w_cnt, max_len); - break; - case SWITCH: - nbgl_serializeSwitch((nbgl_switch_t *) obj, out, w_cnt, max_len); - break; - case PAGE_INDICATOR: - nbgl_serializeNavigationBar((nbgl_page_indicator_t *) obj, out, w_cnt, max_len); - break; - case PROGRESS_BAR: - nbgl_serializeProgressBar((nbgl_progress_bar_t *) obj, out, w_cnt, max_len); - break; - case RADIO_BUTTON: - nbgl_serializeRadio((nbgl_radio_t *) obj, out, w_cnt, max_len); - break; - case QR_CODE: - nbgl_serializeQrCode((nbgl_qrcode_t *) obj, out, w_cnt, max_len); - break; - case KEYBOARD: - nbgl_serializeKeyboard((nbgl_keyboard_t *) obj, out, w_cnt, max_len); - break; - case KEYPAD: - nbgl_serializeKeypad((nbgl_keypad_t *) obj, out, w_cnt, max_len); - break; - case SPINNER: - nbgl_serializeSpinner((nbgl_spinner_t *) obj, out, w_cnt, max_len); - break; - case IMAGE_FILE: - nbgl_serializeImageFile((nbgl_image_file_t *) obj, out, w_cnt, max_len); - break; - default: - return NBGL_SERIALIZE_ERROR; - } - return NBGL_SERIALIZE_OK; +static uint8_t nbgl_serializeObject(nbgl_obj_t *obj, uint8_t *out, size_t *w_cnt, size_t max_len) +{ + switch (obj->type) { + case SCREEN: + return NBGL_SERIALIZE_ERROR; + case CONTAINER: + nbgl_serializeContainer((nbgl_container_t *) obj, out, w_cnt, max_len); + break; + case IMAGE: + nbgl_serializeImage((nbgl_image_t *) obj, out, w_cnt, max_len); + break; + case LINE: + nbgl_serializeLine((nbgl_line_t *) obj, out, w_cnt, max_len); + break; + case TEXT_AREA: + nbgl_serializeTextArea((nbgl_text_area_t *) obj, out, w_cnt, max_len); + break; + case BUTTON: + nbgl_serializeButton((nbgl_button_t *) obj, out, w_cnt, max_len); + break; + case SWITCH: + nbgl_serializeSwitch((nbgl_switch_t *) obj, out, w_cnt, max_len); + break; + case PAGE_INDICATOR: + nbgl_serializeNavigationBar((nbgl_page_indicator_t *) obj, out, w_cnt, max_len); + break; + case PROGRESS_BAR: + nbgl_serializeProgressBar((nbgl_progress_bar_t *) obj, out, w_cnt, max_len); + break; + case RADIO_BUTTON: + nbgl_serializeRadio((nbgl_radio_t *) obj, out, w_cnt, max_len); + break; + case QR_CODE: + nbgl_serializeQrCode((nbgl_qrcode_t *) obj, out, w_cnt, max_len); + break; + case KEYBOARD: + nbgl_serializeKeyboard((nbgl_keyboard_t *) obj, out, w_cnt, max_len); + break; + case KEYPAD: + nbgl_serializeKeypad((nbgl_keypad_t *) obj, out, w_cnt, max_len); + break; + case SPINNER: + nbgl_serializeSpinner((nbgl_spinner_t *) obj, out, w_cnt, max_len); + break; + case IMAGE_FILE: + nbgl_serializeImageFile((nbgl_image_file_t *) obj, out, w_cnt, max_len); + break; + default: + return NBGL_SERIALIZE_ERROR; + } + return NBGL_SERIALIZE_OK; } - -static uint8_t nbgl_serializeRefreshEvent(nbgl_area_t *obj, uint8_t *out, size_t *w_cnt, size_t max_len) { - nbgl_serializeArea(obj, out, w_cnt, max_len); - return NBGL_SERIALIZE_OK; +static uint8_t nbgl_serializeRefreshEvent(nbgl_area_t *obj, + uint8_t *out, + size_t *w_cnt, + size_t max_len) +{ + nbgl_serializeArea(obj, out, w_cnt, max_len); + return NBGL_SERIALIZE_OK; } uint8_t nbgl_serializeNbglEvent(nbgl_serialized_event_type_e type, - nbgl_obj_t *obj, - uint8_t *out, - size_t *w_cnt, - size_t max_len) { - // Write type - nbgl_appendU8((uint8_t) type, out, w_cnt, max_len); - - // Write content - switch(type) { - case NBGL_DRAW_OBJ: - return nbgl_serializeObject(obj, out, w_cnt, max_len); - case NBGL_REFRESH_AREA: - return nbgl_serializeRefreshEvent((nbgl_area_t *) obj, out, w_cnt, max_len); - default: - return NBGL_SERIALIZE_ERROR; - } - - return NBGL_SERIALIZE_OK; + nbgl_obj_t *obj, + uint8_t *out, + size_t *w_cnt, + size_t max_len) +{ + // Write type + nbgl_appendU8((uint8_t) type, out, w_cnt, max_len); + + // Write content + switch (type) { + case NBGL_DRAW_OBJ: + return nbgl_serializeObject(obj, out, w_cnt, max_len); + case NBGL_REFRESH_AREA: + return nbgl_serializeRefreshEvent((nbgl_area_t *) obj, out, w_cnt, max_len); + default: + return NBGL_SERIALIZE_ERROR; + } + + return NBGL_SERIALIZE_OK; } diff --git a/lib_nbgl/src/nbgl_touch.c b/lib_nbgl/src/nbgl_touch.c index 9355025ea..471eaa332 100644 --- a/lib_nbgl/src/nbgl_touch.c +++ b/lib_nbgl/src/nbgl_touch.c @@ -28,10 +28,10 @@ /********************** * STATIC VARIABLES **********************/ -static uint32_t lastPressedTime = 0; -static uint32_t lastCurrentTime = 0; -static nbgl_obj_t *lastPressedObj = NULL; -static nbgl_touchStatePosition_t firstTouchedPosition,lastTouchedPosition; +static uint32_t lastPressedTime = 0; +static uint32_t lastCurrentTime = 0; +static nbgl_obj_t *lastPressedObj = NULL; +static nbgl_touchStatePosition_t firstTouchedPosition, lastTouchedPosition; /********************** * VARIABLES @@ -47,33 +47,34 @@ static nbgl_touchStatePosition_t firstTouchedPosition,lastTouchedPosition; * @param obj object on which the event is applied * @param eventType type of touchscreen event */ -static void applytouchStatePosition(nbgl_obj_t *obj, nbgl_touchType_t eventType) { - nbgl_screen_t *screen = (nbgl_screen_t*)nbgl_screenGetTop(); - LOG_DEBUG(TOUCH_LOGGER,"Apply event %d on object of type %d\n",eventType,obj->type); - if (!obj) { - return; - } - /* the first action is the one provided by the application */ - if ((obj->touchMask & (1<type) { +static void applytouchStatePosition(nbgl_obj_t *obj, nbgl_touchType_t eventType) +{ + nbgl_screen_t *screen = (nbgl_screen_t *) nbgl_screenGetTop(); + LOG_DEBUG(TOUCH_LOGGER, "Apply event %d on object of type %d\n", eventType, obj->type); + if (!obj) { + return; + } + /* the first action is the one provided by the application */ + if ((obj->touchMask & (1 << eventType)) != 0) { + // for some specific objects, call directly a specific callback + switch (obj->type) { #ifdef NBGL_KEYBOARD - case KEYBOARD: - nbgl_keyboardTouchCallback(obj,eventType); - break; -#endif // NBGL_KEYBOARD + case KEYBOARD: + nbgl_keyboardTouchCallback(obj, eventType); + break; +#endif // NBGL_KEYBOARD #ifdef NBGL_KEYPAD - case KEYPAD: - nbgl_keypadTouchCallback(obj,eventType); - break; -#endif // NBGL_KEYPAD - default: - if (screen->touchCallback != NULL) - ((nbgl_touchCallback_t)PIC(screen->touchCallback))((void *)obj, eventType); - break; + case KEYPAD: + nbgl_keypadTouchCallback(obj, eventType); + break; +#endif // NBGL_KEYPAD + default: + if (screen->touchCallback != NULL) { + ((nbgl_touchCallback_t) PIC(screen->touchCallback))((void *) obj, eventType); + } + break; + } } - - } } /** @@ -85,42 +86,42 @@ static void applytouchStatePosition(nbgl_obj_t *obj, nbgl_touchType_t eventType) * @param event * @return the concerned object or NULL if not found */ -static nbgl_obj_t * getTouchedObject(nbgl_obj_t *obj, nbgl_touchStatePosition_t *event) { - if (obj == NULL) { - return NULL; - } - /* check coordinates - no need to go further if the touched point is not within the object - And because the children are also within the object, no need to check them either */ - if ((event->x < obj->area.x0) || (event->x >= (obj->area.x0+obj->area.width)) || - (event->y < obj->area.y0) || (event->y >= (obj->area.y0+obj->area.height))) { - return NULL; - } - if ((obj->type == SCREEN) || - (obj->type == CONTAINER)) { - nbgl_container_t *container = (nbgl_container_t *)obj; - // parse the children, if any - if (container->children != NULL) { - uint8_t i; - for (i=0;inbChildren;i++) { - nbgl_obj_t *current = container->children[i]; - if (current != NULL) { - current = getTouchedObject(current,event); - if (current != NULL) { - return current; - } +static nbgl_obj_t *getTouchedObject(nbgl_obj_t *obj, nbgl_touchStatePosition_t *event) +{ + if (obj == NULL) { + return NULL; + } + /* check coordinates + no need to go further if the touched point is not within the object + And because the children are also within the object, no need to check them either */ + if ((event->x < obj->area.x0) || (event->x >= (obj->area.x0 + obj->area.width)) + || (event->y < obj->area.y0) || (event->y >= (obj->area.y0 + obj->area.height))) { + return NULL; + } + if ((obj->type == SCREEN) || (obj->type == CONTAINER)) { + nbgl_container_t *container = (nbgl_container_t *) obj; + // parse the children, if any + if (container->children != NULL) { + uint8_t i; + for (i = 0; i < container->nbChildren; i++) { + nbgl_obj_t *current = container->children[i]; + if (current != NULL) { + current = getTouchedObject(current, event); + if (current != NULL) { + return current; + } + } + } } - } } - } - /* now see if the object is interested by touch events (any of them) */ - if (obj->touchMask != 0) { - //LOG_DEBUG(TOUCH_LOGGER,"%d %d \n",clickableObjectTypes ,(1<type)); - return obj; - } - else { - return NULL; - } + /* now see if the object is interested by touch events (any of them) */ + if (obj->touchMask != 0) { + // LOG_DEBUG(TOUCH_LOGGER,"%d %d \n",clickableObjectTypes ,(1<type)); + return obj; + } + else { + return NULL; + } } /********************** @@ -133,104 +134,110 @@ static nbgl_obj_t * getTouchedObject(nbgl_obj_t *obj, nbgl_touchStatePosition_t * @param touchStatePosition state and position read from touch screen * @param currentTime current time in ms */ -void nbgl_touchHandler(nbgl_touchStatePosition_t *touchStatePosition, uint32_t currentTime) { - static nbgl_touchState_t lastState = RELEASED; - nbgl_obj_t *foundObj; - - // save last received currentTime - lastCurrentTime = currentTime; - - if (lastState == RELEASED) { - // filter out not realistic cases (successive RELEASE events) - if (RELEASED == touchStatePosition->state) { - lastState = touchStatePosition->state; - return; - } - // memorize first touched position - memcpy(&firstTouchedPosition, touchStatePosition, sizeof(nbgl_touchStatePosition_t)); - } - //LOG_DEBUG(TOUCH_LOGGER,"state = %s, x = %d, y=%d\n",(touchStatePosition->state == RELEASED)?"RELEASED":"PRESSED",touchStatePosition->x,touchStatePosition->y); - - //parse the whole screen to find proper object - foundObj = getTouchedObject(nbgl_screenGetTop(),touchStatePosition); - - //LOG_DEBUG(TOUCH_LOGGER,"nbgl_touchHandler: found obj %p, type = %d\n",foundObj, foundObj->type); - if (foundObj == NULL) { - LOG_DEBUG(TOUCH_LOGGER,"nbgl_touchHandler: no found obj\n"); - if ((touchStatePosition->state == PRESSED) && - (lastState == PRESSED) && - (lastPressedObj != NULL)) { - // finger has moved out of an object - // make sure lastPressedObj still belongs to current screen before warning it - if (nbgl_screenContainsObj(lastPressedObj)) { - applytouchStatePosition(lastPressedObj,OUT_OF_TOUCH); - } +void nbgl_touchHandler(nbgl_touchStatePosition_t *touchStatePosition, uint32_t currentTime) +{ + static nbgl_touchState_t lastState = RELEASED; + nbgl_obj_t *foundObj; + + // save last received currentTime + lastCurrentTime = currentTime; + + if (lastState == RELEASED) { + // filter out not realistic cases (successive RELEASE events) + if (RELEASED == touchStatePosition->state) { + lastState = touchStatePosition->state; + return; + } + // memorize first touched position + memcpy(&firstTouchedPosition, touchStatePosition, sizeof(nbgl_touchStatePosition_t)); } - lastPressedObj = NULL; - lastState = touchStatePosition->state; - return; - } - - // memorize last touched position - memcpy(&lastTouchedPosition, touchStatePosition, sizeof(nbgl_touchStatePosition_t)); - - if (touchStatePosition->state == RELEASED) { - // very strange if lastPressedObj != foundObj, let's consider that it's a normal release on lastPressedObj - // make sure lastPressedObj still belongs to current screen before "releasing" it - if ((lastPressedObj != NULL) && - ((foundObj == lastPressedObj) || - (nbgl_screenContainsObj(lastPressedObj)))){ - applytouchStatePosition(lastPressedObj,TOUCH_RELEASED); - if (currentTime >= (lastPressedTime+LONG_TOUCH_DURATION)) { - applytouchStatePosition(lastPressedObj,LONG_TOUCHED); - } - else if (currentTime >= (lastPressedTime+SHORT_TOUCH_DURATION)) { - applytouchStatePosition(lastPressedObj,TOUCHED); - } + // LOG_DEBUG(TOUCH_LOGGER,"state = %s, x = %d, y=%d\n",(touchStatePosition->state == + // RELEASED)?"RELEASED":"PRESSED",touchStatePosition->x,touchStatePosition->y); + + // parse the whole screen to find proper object + foundObj = getTouchedObject(nbgl_screenGetTop(), touchStatePosition); + + // LOG_DEBUG(TOUCH_LOGGER,"nbgl_touchHandler: found obj %p, type = %d\n",foundObj, + // foundObj->type); + if (foundObj == NULL) { + LOG_DEBUG(TOUCH_LOGGER, "nbgl_touchHandler: no found obj\n"); + if ((touchStatePosition->state == PRESSED) && (lastState == PRESSED) + && (lastPressedObj != NULL)) { + // finger has moved out of an object + // make sure lastPressedObj still belongs to current screen before warning it + if (nbgl_screenContainsObj(lastPressedObj)) { + applytouchStatePosition(lastPressedObj, OUT_OF_TOUCH); + } + } + lastPressedObj = NULL; + lastState = touchStatePosition->state; + return; } - // Released event has been handled, forget lastPressedObj - lastPressedObj = NULL; - } - else { // PRESSED - if ((lastState == PRESSED) && (lastPressedObj != NULL)) { - if (foundObj != lastPressedObj) { - // finger has moved out of an object - // make sure lastPressedObj still belongs to current screen before warning it - if (nbgl_screenContainsObj(lastPressedObj)) { - applytouchStatePosition(lastPressedObj,OUT_OF_TOUCH); + + // memorize last touched position + memcpy(&lastTouchedPosition, touchStatePosition, sizeof(nbgl_touchStatePosition_t)); + + if (touchStatePosition->state == RELEASED) { + // very strange if lastPressedObj != foundObj, let's consider that it's a normal release on + // lastPressedObj make sure lastPressedObj still belongs to current screen before + // "releasing" it + if ((lastPressedObj != NULL) + && ((foundObj == lastPressedObj) || (nbgl_screenContainsObj(lastPressedObj)))) { + applytouchStatePosition(lastPressedObj, TOUCH_RELEASED); + if (currentTime >= (lastPressedTime + LONG_TOUCH_DURATION)) { + applytouchStatePosition(lastPressedObj, LONG_TOUCHED); + } + else if (currentTime >= (lastPressedTime + SHORT_TOUCH_DURATION)) { + applytouchStatePosition(lastPressedObj, TOUCHED); + } } + // Released event has been handled, forget lastPressedObj lastPressedObj = NULL; - } - else { - // warn the concerned object that it is still touched - applytouchStatePosition(foundObj,TOUCHING); - } } - else if (lastState == RELEASED) { - // newly touched object - lastPressedObj = foundObj; - lastPressedTime = currentTime; - applytouchStatePosition(foundObj,TOUCH_PRESSED); - applytouchStatePosition(foundObj,TOUCHING); + else { // PRESSED + if ((lastState == PRESSED) && (lastPressedObj != NULL)) { + if (foundObj != lastPressedObj) { + // finger has moved out of an object + // make sure lastPressedObj still belongs to current screen before warning it + if (nbgl_screenContainsObj(lastPressedObj)) { + applytouchStatePosition(lastPressedObj, OUT_OF_TOUCH); + } + lastPressedObj = NULL; + } + else { + // warn the concerned object that it is still touched + applytouchStatePosition(foundObj, TOUCHING); + } + } + else if (lastState == RELEASED) { + // newly touched object + lastPressedObj = foundObj; + lastPressedTime = currentTime; + applytouchStatePosition(foundObj, TOUCH_PRESSED); + applytouchStatePosition(foundObj, TOUCHING); + } } - } - lastState = touchStatePosition->state; + lastState = touchStatePosition->state; } -bool nbgl_touchGetTouchedPosition(nbgl_obj_t *obj, nbgl_touchStatePosition_t **firstPos, nbgl_touchStatePosition_t **lastPos) { - LOG_DEBUG(TOUCH_LOGGER,"nbgl_touchGetTouchedPosition: %p %p\n", obj,lastPressedObj); - if (obj == lastPressedObj) { - *firstPos = &firstTouchedPosition; - *lastPos = &lastTouchedPosition; - return true; - } - return false; +bool nbgl_touchGetTouchedPosition(nbgl_obj_t *obj, + nbgl_touchStatePosition_t **firstPos, + nbgl_touchStatePosition_t **lastPos) +{ + LOG_DEBUG(TOUCH_LOGGER, "nbgl_touchGetTouchedPosition: %p %p\n", obj, lastPressedObj); + if (obj == lastPressedObj) { + *firstPos = &firstTouchedPosition; + *lastPos = &lastTouchedPosition; + return true; + } + return false; } -uint32_t nbgl_touchGetTouchDuration(nbgl_obj_t *obj) { - if (obj == lastPressedObj) { - return (lastCurrentTime-lastPressedTime); - } - return 0; +uint32_t nbgl_touchGetTouchDuration(nbgl_obj_t *obj) +{ + if (obj == lastPressedObj) { + return (lastCurrentTime - lastPressedTime); + } + return 0; } diff --git a/lib_nbgl/src/nbgl_use_case.c b/lib_nbgl/src/nbgl_use_case.c index 910d07461..653cf3ba4 100644 --- a/lib_nbgl/src/nbgl_use_case.c +++ b/lib_nbgl/src/nbgl_use_case.c @@ -22,46 +22,45 @@ * TYPEDEFS **********************/ enum { - BACK_TOKEN=0, - NEXT_TOKEN, - QUIT_TOKEN, - NAV_TOKEN, - SKIP_TOKEN, - CONTINUE_TOKEN, - BUTTON_TOKEN, - ACTION_BUTTON_TOKEN, - CHOICE_TOKEN, - DETAILS_BUTTON_TOKEN, - CONFIRM_TOKEN, - REJECT_TOKEN, - ADDR_BACK_TOKEN, - ADDR_NEXT_TOKEN + BACK_TOKEN = 0, + NEXT_TOKEN, + QUIT_TOKEN, + NAV_TOKEN, + SKIP_TOKEN, + CONTINUE_TOKEN, + BUTTON_TOKEN, + ACTION_BUTTON_TOKEN, + CHOICE_TOKEN, + DETAILS_BUTTON_TOKEN, + CONFIRM_TOKEN, + REJECT_TOKEN, + ADDR_BACK_TOKEN, + ADDR_NEXT_TOKEN }; typedef struct DetailsContext_s { - uint8_t nbPages; - uint8_t currentPage; - bool wrapping; - const char *tag; - const char *value; - const char *nextPageStart; + uint8_t nbPages; + uint8_t currentPage; + bool wrapping; + const char *tag; + const char *value; + const char *nextPageStart; } DetailsContext_t; typedef struct StaticReviewContext_s { - nbgl_layoutTagValueList_t tagValueList; - bool withLongPress; - nbgl_pageInfoLongPress_t infoLongPress; - uint8_t currentPairIndex; - uint8_t nbPairsInCurrentPage; + nbgl_layoutTagValueList_t tagValueList; + bool withLongPress; + nbgl_pageInfoLongPress_t infoLongPress; + uint8_t currentPairIndex; + uint8_t nbPairsInCurrentPage; } StaticReviewContext_t; typedef struct AddressConfirmationContext_s { - const char *address; - nbgl_layout_t modalLayout; - const nbgl_layoutTagValueList_t *tagValueList; + const char *address; + nbgl_layout_t modalLayout; + const nbgl_layoutTagValueList_t *tagValueList; } AddressConfirmationContext_t; - /********************** * STATIC VARIABLES **********************/ @@ -70,23 +69,23 @@ static char appDescription[APP_DESCRIPTION_MAX_LEN]; static char plugInDescription[APP_DESCRIPTION_MAX_LEN]; // multi-purposes callbacks -static nbgl_callback_t onQuit; -static nbgl_callback_t onContinue; -static nbgl_callback_t onAction; -static nbgl_navCallback_t onNav; +static nbgl_callback_t onQuit; +static nbgl_callback_t onContinue; +static nbgl_callback_t onAction; +static nbgl_navCallback_t onNav; static nbgl_layoutTouchCallback_t onControls; -static nbgl_choiceCallback_t onChoice; -static nbgl_callback_t onModalConfirm; +static nbgl_choiceCallback_t onChoice; +static nbgl_callback_t onModalConfirm; // contexts for background and modal pages static nbgl_page_t *pageContext; static nbgl_page_t *modalPageContext; // context for settings pages -static const char *settingsTitle; -static bool touchableTitle; +static const char *settingsTitle; +static bool touchableTitle; static nbgl_pageNavigationInfo_t navInfo; -static bool forwardNavOnly; +static bool forwardNavOnly; static DetailsContext_t detailsContext; @@ -111,524 +110,575 @@ static void displayStaticReviewPage(uint8_t page, bool forceFullRefresh); static void pageCallback(int token, uint8_t index); #ifdef NBGL_QRCODE static void addressLayoutTouchCallbackQR(int token, uint8_t index); -#endif // NBGL_QRCODE -static void displayAddressPage(uint8_t page, bool forceFullRefresh); -static void displaySkipWarning(void); +#endif // NBGL_QRCODE +static void displayAddressPage(uint8_t page, bool forceFullRefresh); +static void displaySkipWarning(void); static uint8_t getNbPairs(uint8_t page, bool *tooLongToFit); // function called when navigating (or exiting) modal details pages // or when skip choice is displayed -static void pageModalCallback(int token, uint8_t index) { - nbgl_pageRelease(modalPageContext); - modalPageContext = NULL; - if (token == NAV_TOKEN) { - if (index == EXIT_PAGE) { - // redraw the background layer - nbgl_screenRedraw(); - nbgl_refresh(); - } - else { - displayDetailsPage(index, false); - } - } - else if (token == SKIP_TOKEN) { - if (index == 0) { - // display the last forward only review page, whatever it is - displayReviewPage(LAST_PAGE_FOR_REVIEW, true); - } - else { - // display background, which should be the page where skip has been touched - nbgl_screenRedraw(); - nbgl_refresh(); +static void pageModalCallback(int token, uint8_t index) +{ + nbgl_pageRelease(modalPageContext); + modalPageContext = NULL; + if (token == NAV_TOKEN) { + if (index == EXIT_PAGE) { + // redraw the background layer + nbgl_screenRedraw(); + nbgl_refresh(); + } + else { + displayDetailsPage(index, false); + } } - } - else if (token == CHOICE_TOKEN) { - if (index == 0) { - onModalConfirm(); + else if (token == SKIP_TOKEN) { + if (index == 0) { + // display the last forward only review page, whatever it is + displayReviewPage(LAST_PAGE_FOR_REVIEW, true); + } + else { + // display background, which should be the page where skip has been touched + nbgl_screenRedraw(); + nbgl_refresh(); + } } - else { - // display background, which should be the page where skip has been touched - nbgl_screenRedraw(); - nbgl_refresh(); + else if (token == CHOICE_TOKEN) { + if (index == 0) { + onModalConfirm(); + } + else { + // display background, which should be the page where skip has been touched + nbgl_screenRedraw(); + nbgl_refresh(); + } } - } } // generic callback for all pages except modal -static void pageCallback(int token, uint8_t index) { - if (token == QUIT_TOKEN) { - if (onQuit != NULL) - onQuit(); - } - else if (token == CONTINUE_TOKEN) { - if (onContinue != NULL) - onContinue(); - } - else if (token == CHOICE_TOKEN) { - if (onChoice != NULL) - onChoice((index == 0)?true:false); - } - else if (token == ACTION_BUTTON_TOKEN) { - if ((index == 0) && (onAction != NULL)) { - onAction(); - } - else if ((index == 1) && (onQuit != NULL)) { - onQuit(); - } - } - else if (token == BUTTON_TOKEN) { +static void pageCallback(int token, uint8_t index) +{ + if (token == QUIT_TOKEN) { + if (onQuit != NULL) { + onQuit(); + } + } + else if (token == CONTINUE_TOKEN) { + if (onContinue != NULL) { + onContinue(); + } + } + else if (token == CHOICE_TOKEN) { + if (onChoice != NULL) { + onChoice((index == 0) ? true : false); + } + } + else if (token == ACTION_BUTTON_TOKEN) { + if ((index == 0) && (onAction != NULL)) { + onAction(); + } + else if ((index == 1) && (onQuit != NULL)) { + onQuit(); + } + } + else if (token == BUTTON_TOKEN) { #ifdef NBGL_QRCODE - // display the address as QR Code - nbgl_layoutDescription_t layoutDescription = { - .modal = true, - .withLeftBorder = true, - .onActionCallback = &addressLayoutTouchCallbackQR, - .tapActionText = NULL - }; - - addressConfirmationContext.modalLayout = nbgl_layoutGet(&layoutDescription); - nbgl_layoutQRCode_t qrCode = { - .url = addressConfirmationContext.address, - .text1 = NULL, - .text2 = addressConfirmationContext.address // display as gray text - }; - nbgl_layoutAddQRCode(addressConfirmationContext.modalLayout, &qrCode); - - nbgl_layoutAddBottomButton(addressConfirmationContext.modalLayout, &C_cross32px, 0, true, TUNE_TAP_CASUAL); - nbgl_layoutDraw(addressConfirmationContext.modalLayout); - nbgl_refresh(); -#endif // NBGL_QRCODE - } - else if (token == CONFIRM_TOKEN) { - if (onChoice != NULL) - onChoice(true); - } - else if (token == REJECT_TOKEN) { - if (onChoice != NULL) - onChoice(false); - } - else if (token == DETAILS_BUTTON_TOKEN) { - nbgl_layoutTagValue_t *pair; - if (staticReviewContext.tagValueList.pairs != NULL) { - pair = &staticReviewContext.tagValueList.pairs[staticReviewContext.currentPairIndex]; + // display the address as QR Code + nbgl_layoutDescription_t layoutDescription + = {.modal = true, + .withLeftBorder = true, + .onActionCallback = &addressLayoutTouchCallbackQR, + .tapActionText = NULL}; + + addressConfirmationContext.modalLayout = nbgl_layoutGet(&layoutDescription); + nbgl_layoutQRCode_t qrCode = { + .url = addressConfirmationContext.address, + .text1 = NULL, + .text2 = addressConfirmationContext.address // display as gray text + }; + nbgl_layoutAddQRCode(addressConfirmationContext.modalLayout, &qrCode); + + nbgl_layoutAddBottomButton( + addressConfirmationContext.modalLayout, &C_cross32px, 0, true, TUNE_TAP_CASUAL); + nbgl_layoutDraw(addressConfirmationContext.modalLayout); + nbgl_refresh(); +#endif // NBGL_QRCODE } - else { - pair = staticReviewContext.tagValueList.callback(staticReviewContext.currentPairIndex); - } - nbgl_useCaseViewDetails(pair->item, - pair->value, - staticReviewContext.tagValueList.wrapping); - } - else if (token == NAV_TOKEN) { - if (index == EXIT_PAGE) { - if (onQuit != NULL) - onQuit(); + else if (token == CONFIRM_TOKEN) { + if (onChoice != NULL) { + onChoice(true); + } + } + else if (token == REJECT_TOKEN) { + if (onChoice != NULL) { + onChoice(false); + } + } + else if (token == DETAILS_BUTTON_TOKEN) { + nbgl_layoutTagValue_t *pair; + if (staticReviewContext.tagValueList.pairs != NULL) { + pair = &staticReviewContext.tagValueList.pairs[staticReviewContext.currentPairIndex]; + } + else { + pair = staticReviewContext.tagValueList.callback(staticReviewContext.currentPairIndex); + } + nbgl_useCaseViewDetails(pair->item, pair->value, staticReviewContext.tagValueList.wrapping); + } + else if (token == NAV_TOKEN) { + if (index == EXIT_PAGE) { + if (onQuit != NULL) { + onQuit(); + } + } + else { + displaySettingsPage(index, false); + } + } + else if (token == NEXT_TOKEN) { + if (onNav != NULL) { + displayReviewPage(navInfo.activePage + 1, false); + } + else { + displayStaticReviewPage(navInfo.activePage + 1, false); + } + } + else if (token == BACK_TOKEN) { + if (onNav != NULL) { + displayReviewPage(navInfo.activePage - 1, true); + } + else { + displayStaticReviewPage(navInfo.activePage - 1, true); + } + } + else if (token == SKIP_TOKEN) { + // display a modal warning to confirm skip + displaySkipWarning(); + } + else if (token == ADDR_BACK_TOKEN) { + displayAddressPage(navInfo.activePage - 1, true); + } + else if (token == ADDR_NEXT_TOKEN) { + displayAddressPage(navInfo.activePage + 1, false); + } + else { // probably a control provided by caller + if (onControls != NULL) { + onControls(token, index); + } } - else { - displaySettingsPage(index, false); - } - } - else if (token == NEXT_TOKEN) { - if (onNav != NULL) - displayReviewPage(navInfo.activePage+1, false); - else - displayStaticReviewPage(navInfo.activePage+1, false); - } - else if (token == BACK_TOKEN) { - if (onNav != NULL) - displayReviewPage(navInfo.activePage-1, true); - else - displayStaticReviewPage(navInfo.activePage-1, true); - } - else if (token == SKIP_TOKEN) { - // display a modal warning to confirm skip - displaySkipWarning(); - } - else if (token == ADDR_BACK_TOKEN) { - displayAddressPage(navInfo.activePage-1, true); - } - else if (token == ADDR_NEXT_TOKEN) { - displayAddressPage(navInfo.activePage+1, false); - } - else { // probably a control provided by caller - if (onControls != NULL) { - onControls(token, index); - } - } } // callback used for confirmation -static void tickerCallback(void) { - nbgl_pageRelease(pageContext); - if (onQuit != NULL) - onQuit(); +static void tickerCallback(void) +{ + nbgl_pageRelease(pageContext); + if (onQuit != NULL) { + onQuit(); + } } // function used to display the current page in review -static void displaySettingsPage(uint8_t page, bool forceFullRefresh) { - nbgl_pageContent_t content; +static void displaySettingsPage(uint8_t page, bool forceFullRefresh) +{ + nbgl_pageContent_t content; - if ((onNav == NULL) || (onNav(page, &content) == false)) - return; + if ((onNav == NULL) || (onNav(page, &content) == false)) { + return; + } - // override some fields - content.title = settingsTitle; - content.isTouchableTitle = touchableTitle; - content.titleToken = QUIT_TOKEN; - content.tuneId = TUNE_TAP_CASUAL; + // override some fields + content.title = settingsTitle; + content.isTouchableTitle = touchableTitle; + content.titleToken = QUIT_TOKEN; + content.tuneId = TUNE_TAP_CASUAL; - navInfo.activePage = page; - pageContext = nbgl_pageDrawGenericContent(&pageCallback, &navInfo, &content); + navInfo.activePage = page; + pageContext = nbgl_pageDrawGenericContent(&pageCallback, &navInfo, &content); - if (forceFullRefresh) { - nbgl_refreshSpecial(FULL_COLOR_CLEAN_REFRESH); - } else { - nbgl_refreshSpecial(FULL_COLOR_PARTIAL_REFRESH); - } + if (forceFullRefresh) { + nbgl_refreshSpecial(FULL_COLOR_CLEAN_REFRESH); + } + else { + nbgl_refreshSpecial(FULL_COLOR_PARTIAL_REFRESH); + } } // function used to display the current page in review -static void displayReviewPage(uint8_t page, bool forceFullRefresh) { - nbgl_pageContent_t content = {0}; - - // ensure the page is valid - if ((navInfo.nbPages != 0) && (page >= (navInfo.nbPages))) { - return; - } - navInfo.activePage = page; - if ((onNav == NULL) || (onNav(navInfo.activePage, &content) == false)) - return; - - // override some fields - content.title = NULL; - content.isTouchableTitle = false; - content.tuneId = TUNE_TAP_CASUAL; - - if (!forwardNavOnly) - navInfo.navWithTap.backButton = (navInfo.activePage==0)?false:true; - - if (content.type == INFO_LONG_PRESS) { // last page - navInfo.navWithTap.nextPageText = NULL; - content.infoLongPress.longPressToken = CONFIRM_TOKEN; - if (forwardNavOnly) { - // remove the "Skip" button in Footer - navInfo.navWithTap.skipText = NULL; - } - } - else { - navInfo.navWithTap.nextPageText = "Tap to continue"; - } - - // override smallCaseForValue for tag/value types to false - if (content.type == TAG_VALUE_DETAILS) { - content.tagValueDetails.tagValueList.smallCaseForValue = false; - // the maximum displayable number of lines for value is NB_MAX_LINES_IN_REVIEW (without More button) - content.tagValueDetails.tagValueList.nbMaxLinesForValue = NB_MAX_LINES_IN_REVIEW; - } - else if (content.type == TAG_VALUE_LIST) { - content.tagValueList.smallCaseForValue = false; - } - else if (content.type == TAG_VALUE_CONFIRM) { - content.tagValueConfirm.tagValueList.smallCaseForValue = false; - // no next because confirmation is always the last page - navInfo.navWithTap.nextPageText = NULL; - // use confirm token for black button - content.tagValueConfirm.confirmationToken = CONFIRM_TOKEN; - } - - pageContext = nbgl_pageDrawGenericContent(&pageCallback, &navInfo, &content); - - if (forceFullRefresh) { - nbgl_refreshSpecial(FULL_COLOR_CLEAN_REFRESH); - } else { - nbgl_refreshSpecial(FULL_COLOR_PARTIAL_REFRESH); - } +static void displayReviewPage(uint8_t page, bool forceFullRefresh) +{ + nbgl_pageContent_t content = {0}; + + // ensure the page is valid + if ((navInfo.nbPages != 0) && (page >= (navInfo.nbPages))) { + return; + } + navInfo.activePage = page; + if ((onNav == NULL) || (onNav(navInfo.activePage, &content) == false)) { + return; + } + + // override some fields + content.title = NULL; + content.isTouchableTitle = false; + content.tuneId = TUNE_TAP_CASUAL; + + if (!forwardNavOnly) { + navInfo.navWithTap.backButton = (navInfo.activePage == 0) ? false : true; + } + + if (content.type == INFO_LONG_PRESS) { // last page + navInfo.navWithTap.nextPageText = NULL; + content.infoLongPress.longPressToken = CONFIRM_TOKEN; + if (forwardNavOnly) { + // remove the "Skip" button in Footer + navInfo.navWithTap.skipText = NULL; + } + } + else { + navInfo.navWithTap.nextPageText = "Tap to continue"; + } + + // override smallCaseForValue for tag/value types to false + if (content.type == TAG_VALUE_DETAILS) { + content.tagValueDetails.tagValueList.smallCaseForValue = false; + // the maximum displayable number of lines for value is NB_MAX_LINES_IN_REVIEW (without More + // button) + content.tagValueDetails.tagValueList.nbMaxLinesForValue = NB_MAX_LINES_IN_REVIEW; + } + else if (content.type == TAG_VALUE_LIST) { + content.tagValueList.smallCaseForValue = false; + } + else if (content.type == TAG_VALUE_CONFIRM) { + content.tagValueConfirm.tagValueList.smallCaseForValue = false; + // no next because confirmation is always the last page + navInfo.navWithTap.nextPageText = NULL; + // use confirm token for black button + content.tagValueConfirm.confirmationToken = CONFIRM_TOKEN; + } + + pageContext = nbgl_pageDrawGenericContent(&pageCallback, &navInfo, &content); + + if (forceFullRefresh) { + nbgl_refreshSpecial(FULL_COLOR_CLEAN_REFRESH); + } + else { + nbgl_refreshSpecial(FULL_COLOR_PARTIAL_REFRESH); + } } // function used to display the current page in static review (no call to user to get content) -static void displayStaticReviewPage(uint8_t page, bool forceFullRefresh) { - nbgl_pageContent_t content; - - // if it's the last page, display a long press button (or a simple button) with the info provided by user (except token) - if (page == (navInfo.nbPages - 1)) { - if (staticReviewContext.withLongPress) { - content.type = INFO_LONG_PRESS; - content.infoLongPress.icon = staticReviewContext.infoLongPress.icon; - content.infoLongPress.longPressText = staticReviewContext.infoLongPress.longPressText; - content.infoLongPress.text = staticReviewContext.infoLongPress.text; - content.infoLongPress.longPressToken = CONFIRM_TOKEN; - content.tuneId = TUNE_TAP_CASUAL; +static void displayStaticReviewPage(uint8_t page, bool forceFullRefresh) +{ + nbgl_pageContent_t content; + + // if it's the last page, display a long press button (or a simple button) with the info + // provided by user (except token) + if (page == (navInfo.nbPages - 1)) { + if (staticReviewContext.withLongPress) { + content.type = INFO_LONG_PRESS; + content.infoLongPress.icon = staticReviewContext.infoLongPress.icon; + content.infoLongPress.longPressText = staticReviewContext.infoLongPress.longPressText; + content.infoLongPress.text = staticReviewContext.infoLongPress.text; + content.infoLongPress.longPressToken = CONFIRM_TOKEN; + content.tuneId = TUNE_TAP_CASUAL; + } + else { + // simple button + content.type = INFO_BUTTON; + content.infoButton.icon = staticReviewContext.infoLongPress.icon; + content.infoButton.buttonText = staticReviewContext.infoLongPress.longPressText; + content.infoButton.text = staticReviewContext.infoLongPress.text; + content.infoButton.buttonToken = CONFIRM_TOKEN; + content.tuneId = TUNE_TAP_CASUAL; + } } else { - // simple button - content.type = INFO_BUTTON; - content.infoButton.icon = staticReviewContext.infoLongPress.icon; - content.infoButton.buttonText = staticReviewContext.infoLongPress.longPressText; - content.infoButton.text = staticReviewContext.infoLongPress.text; - content.infoButton.buttonToken = CONFIRM_TOKEN; - content.tuneId = TUNE_TAP_CASUAL; - } - } - else { - bool tooLongToFit; - - if (page > navInfo.activePage) { // forward, so add to current index the number of pairs of the previous page - staticReviewContext.currentPairIndex += staticReviewContext.nbPairsInCurrentPage; - } - staticReviewContext.nbPairsInCurrentPage = getNbPairs(page,&tooLongToFit); - // if the page is not the last tag/value or when going forward, adapt index - if ((page != (navInfo.nbPages - 2)) && (page < navInfo.activePage)) { // backward - staticReviewContext.currentPairIndex -= staticReviewContext.nbPairsInCurrentPage; - } - // if the pair is too long to fit, we use a TAG_VALUE_DETAILS content - if (tooLongToFit) { - content.type = TAG_VALUE_DETAILS; - content.tagValueDetails.detailsButtonText = "More"; - content.tagValueDetails.detailsButtonIcon = NULL; - content.tagValueDetails.detailsButtonToken = DETAILS_BUTTON_TOKEN; - content.tagValueDetails.tagValueList.nbMaxLinesForValue = NB_MAX_LINES_IN_REVIEW; - content.tagValueDetails.tagValueList.nbPairs = 1; - if (staticReviewContext.tagValueList.pairs != NULL) { - content.tagValueDetails.tagValueList.pairs = &staticReviewContext.tagValueList.pairs[staticReviewContext.currentPairIndex]; - } - else { - content.tagValueDetails.tagValueList.pairs = staticReviewContext.tagValueList.callback(staticReviewContext.currentPairIndex); - } - content.tagValueDetails.tagValueList.smallCaseForValue = false; - content.tagValueDetails.tagValueList.wrapping = staticReviewContext.tagValueList.wrapping; + bool tooLongToFit; + + if (page > navInfo.activePage) { // forward, so add to current index the number of pairs of + // the previous page + staticReviewContext.currentPairIndex += staticReviewContext.nbPairsInCurrentPage; + } + staticReviewContext.nbPairsInCurrentPage = getNbPairs(page, &tooLongToFit); + // if the page is not the last tag/value or when going forward, adapt index + if ((page != (navInfo.nbPages - 2)) && (page < navInfo.activePage)) { // backward + staticReviewContext.currentPairIndex -= staticReviewContext.nbPairsInCurrentPage; + } + // if the pair is too long to fit, we use a TAG_VALUE_DETAILS content + if (tooLongToFit) { + content.type = TAG_VALUE_DETAILS; + content.tagValueDetails.detailsButtonText = "More"; + content.tagValueDetails.detailsButtonIcon = NULL; + content.tagValueDetails.detailsButtonToken = DETAILS_BUTTON_TOKEN; + content.tagValueDetails.tagValueList.nbMaxLinesForValue = NB_MAX_LINES_IN_REVIEW; + content.tagValueDetails.tagValueList.nbPairs = 1; + if (staticReviewContext.tagValueList.pairs != NULL) { + content.tagValueDetails.tagValueList.pairs + = &staticReviewContext.tagValueList.pairs[staticReviewContext.currentPairIndex]; + } + else { + content.tagValueDetails.tagValueList.pairs + = staticReviewContext.tagValueList.callback( + staticReviewContext.currentPairIndex); + } + content.tagValueDetails.tagValueList.smallCaseForValue = false; + content.tagValueDetails.tagValueList.wrapping + = staticReviewContext.tagValueList.wrapping; + } + else { + content.type = TAG_VALUE_LIST; + content.tagValueList.nbPairs = staticReviewContext.nbPairsInCurrentPage; + if (staticReviewContext.tagValueList.pairs != NULL) { + content.tagValueList.pairs + = &staticReviewContext.tagValueList.pairs[staticReviewContext.currentPairIndex]; + } + else { + content.tagValueList.pairs = NULL; + content.tagValueList.callback = staticReviewContext.tagValueList.callback; + content.tagValueList.startIndex = staticReviewContext.currentPairIndex; + } + content.tagValueList.smallCaseForValue = false; + content.tagValueList.nbMaxLinesForValue = NB_MAX_LINES_IN_REVIEW; + content.tagValueList.wrapping = staticReviewContext.tagValueList.wrapping; + } + content.tuneId = TUNE_TAP_CASUAL; + } + navInfo.activePage = page; + + // common fields + content.title = NULL; + content.isTouchableTitle = false; + + navInfo.navWithTap.backButton = (navInfo.activePage == 0) ? false : true; + + if (navInfo.activePage == (navInfo.nbPages - 1)) { + navInfo.navWithTap.nextPageText = NULL; } else { - content.type = TAG_VALUE_LIST; - content.tagValueList.nbPairs = staticReviewContext.nbPairsInCurrentPage; - if (staticReviewContext.tagValueList.pairs != NULL) { - content.tagValueList.pairs = &staticReviewContext.tagValueList.pairs[staticReviewContext.currentPairIndex]; - } - else { - content.tagValueList.pairs = NULL; - content.tagValueList.callback = staticReviewContext.tagValueList.callback; - content.tagValueList.startIndex = staticReviewContext.currentPairIndex; - } - content.tagValueList.smallCaseForValue = false; - content.tagValueList.nbMaxLinesForValue = NB_MAX_LINES_IN_REVIEW; - content.tagValueList.wrapping = staticReviewContext.tagValueList.wrapping; - } - content.tuneId = TUNE_TAP_CASUAL; - } - navInfo.activePage = page; - - // common fields - content.title = NULL; - content.isTouchableTitle = false; - - navInfo.navWithTap.backButton = (navInfo.activePage==0)?false:true; - - if (navInfo.activePage == (navInfo.nbPages-1)) { - navInfo.navWithTap.nextPageText = NULL; - } - else { - navInfo.navWithTap.nextPageText = "Tap to continue"; - } - - pageContext = nbgl_pageDrawGenericContent(&pageCallback, &navInfo, &content); - - if (forceFullRefresh) { - nbgl_refreshSpecial(FULL_COLOR_CLEAN_REFRESH); - } else { - nbgl_refreshSpecial(FULL_COLOR_PARTIAL_REFRESH); - } + navInfo.navWithTap.nextPageText = "Tap to continue"; + } + + pageContext = nbgl_pageDrawGenericContent(&pageCallback, &navInfo, &content); + + if (forceFullRefresh) { + nbgl_refreshSpecial(FULL_COLOR_CLEAN_REFRESH); + } + else { + nbgl_refreshSpecial(FULL_COLOR_PARTIAL_REFRESH); + } } // from the current details context, return a pointer on the details at the given page -static const char *getDetailsPageAt(uint8_t detailsPage) { - uint8_t page = 0; - const char *currentChar = detailsContext.value; - while (pageNB_MAX_LINES_IN_DETAILS) { - uint16_t len; - nbgl_getTextMaxLenInNbLines(BAGL_FONT_INTER_REGULAR_24px, currentChar,SCREEN_WIDTH-2*BORDER_MARGIN,NB_MAX_LINES_IN_DETAILS,&len); - len-=3; - currentChar = currentChar+len; - } - page++; - } - return currentChar; +static const char *getDetailsPageAt(uint8_t detailsPage) +{ + uint8_t page = 0; + const char *currentChar = detailsContext.value; + while (page < detailsPage) { + uint16_t nbLines = nbgl_getTextNbLinesInWidth( + BAGL_FONT_INTER_REGULAR_24px, currentChar, SCREEN_WIDTH - 2 * BORDER_MARGIN, false); + if (nbLines > NB_MAX_LINES_IN_DETAILS) { + uint16_t len; + nbgl_getTextMaxLenInNbLines(BAGL_FONT_INTER_REGULAR_24px, + currentChar, + SCREEN_WIDTH - 2 * BORDER_MARGIN, + NB_MAX_LINES_IN_DETAILS, + &len); + len -= 3; + currentChar = currentChar + len; + } + page++; + } + return currentChar; } // function used to display the current page in details review mode -static void displayDetailsPage(uint8_t detailsPage, bool forceFullRefresh) { - static nbgl_layoutTagValue_t currentPair; - nbgl_pageNavigationInfo_t info = { - .activePage = detailsPage, - .nbPages = detailsContext.nbPages, - .navType = NAV_WITH_BUTTONS, - .navWithButtons.navToken = NAV_TOKEN, - .navWithButtons.quitButton = true, - .progressIndicator = true, - .tuneId = TUNE_TAP_CASUAL - }; - nbgl_pageContent_t content = { - .type = TAG_VALUE_LIST, - .tagValueList.nbPairs = 1, - .tagValueList.pairs = ¤tPair, - .tagValueList.smallCaseForValue = true, - .tagValueList.wrapping = detailsContext.wrapping - }; - - if (modalPageContext != NULL) { - nbgl_pageRelease(modalPageContext); - } - currentPair.item = detailsContext.tag; - // if move backward or first page - if (detailsPage <= detailsContext.currentPage) { - // recompute current start from beginning - currentPair.value = getDetailsPageAt(detailsPage); - forceFullRefresh = true; - } - // else move forward - else { - currentPair.value = detailsContext.nextPageStart; - } - detailsContext.currentPage = detailsPage; - uint16_t nbLines = nbgl_getTextNbLinesInWidth(BAGL_FONT_INTER_REGULAR_24px, currentPair.value, SCREEN_WIDTH-2*BORDER_MARGIN, false); - - if (nbLines>NB_MAX_LINES_IN_DETAILS) { - uint16_t len; - nbgl_getTextMaxLenInNbLines(BAGL_FONT_INTER_REGULAR_24px, currentPair.value,SCREEN_WIDTH-2*BORDER_MARGIN,NB_MAX_LINES_IN_DETAILS,&len); - len-=3; - // memorize next position to save processing - detailsContext.nextPageStart = currentPair.value+len; - // use special feature to keep only NB_MAX_LINES_IN_DETAILS lines and replace the last 3 chars by "..." - content.tagValueList.nbMaxLinesForValue = NB_MAX_LINES_IN_DETAILS; - } - else { - detailsContext.nextPageStart = NULL; - content.tagValueList.nbMaxLinesForValue = 0; - } - modalPageContext = nbgl_pageDrawGenericContentExt(&pageModalCallback, &info, &content, true); - - if (forceFullRefresh) { - nbgl_refreshSpecial(FULL_COLOR_CLEAN_REFRESH); - } else { - nbgl_refreshSpecial(FULL_COLOR_PARTIAL_REFRESH); - } +static void displayDetailsPage(uint8_t detailsPage, bool forceFullRefresh) +{ + static nbgl_layoutTagValue_t currentPair; + nbgl_pageNavigationInfo_t info = {.activePage = detailsPage, + .nbPages = detailsContext.nbPages, + .navType = NAV_WITH_BUTTONS, + .navWithButtons.navToken = NAV_TOKEN, + .navWithButtons.quitButton = true, + .progressIndicator = true, + .tuneId = TUNE_TAP_CASUAL}; + nbgl_pageContent_t content = {.type = TAG_VALUE_LIST, + .tagValueList.nbPairs = 1, + .tagValueList.pairs = ¤tPair, + .tagValueList.smallCaseForValue = true, + .tagValueList.wrapping = detailsContext.wrapping}; + + if (modalPageContext != NULL) { + nbgl_pageRelease(modalPageContext); + } + currentPair.item = detailsContext.tag; + // if move backward or first page + if (detailsPage <= detailsContext.currentPage) { + // recompute current start from beginning + currentPair.value = getDetailsPageAt(detailsPage); + forceFullRefresh = true; + } + // else move forward + else { + currentPair.value = detailsContext.nextPageStart; + } + detailsContext.currentPage = detailsPage; + uint16_t nbLines = nbgl_getTextNbLinesInWidth( + BAGL_FONT_INTER_REGULAR_24px, currentPair.value, SCREEN_WIDTH - 2 * BORDER_MARGIN, false); + + if (nbLines > NB_MAX_LINES_IN_DETAILS) { + uint16_t len; + nbgl_getTextMaxLenInNbLines(BAGL_FONT_INTER_REGULAR_24px, + currentPair.value, + SCREEN_WIDTH - 2 * BORDER_MARGIN, + NB_MAX_LINES_IN_DETAILS, + &len); + len -= 3; + // memorize next position to save processing + detailsContext.nextPageStart = currentPair.value + len; + // use special feature to keep only NB_MAX_LINES_IN_DETAILS lines and replace the last 3 + // chars by "..." + content.tagValueList.nbMaxLinesForValue = NB_MAX_LINES_IN_DETAILS; + } + else { + detailsContext.nextPageStart = NULL; + content.tagValueList.nbMaxLinesForValue = 0; + } + modalPageContext = nbgl_pageDrawGenericContentExt(&pageModalCallback, &info, &content, true); + + if (forceFullRefresh) { + nbgl_refreshSpecial(FULL_COLOR_CLEAN_REFRESH); + } + else { + nbgl_refreshSpecial(FULL_COLOR_PARTIAL_REFRESH); + } } #ifdef NBGL_QRCODE // called when quit button is touched on Address verification page -static void addressLayoutTouchCallbackQR(int token, uint8_t index) { - UNUSED(token); - UNUSED(index); - - // dismiss modal - nbgl_layoutRelease(addressConfirmationContext.modalLayout); - nbgl_screenRedraw(); - nbgl_refresh(); +static void addressLayoutTouchCallbackQR(int token, uint8_t index) +{ + UNUSED(token); + UNUSED(index); + + // dismiss modal + nbgl_layoutRelease(addressConfirmationContext.modalLayout); + nbgl_screenRedraw(); + nbgl_refresh(); } -#endif // NBGL_QRCODE +#endif // NBGL_QRCODE // called when navigation is touched on Address verification page -static void displayAddressPage(uint8_t page, bool forceFullRefresh) { - nbgl_pageContent_t content; - nbgl_layoutTagValue_t tagValuePair = { - .item = "Address", - .value = addressConfirmationContext.address - }; - - content.type = TAG_VALUE_CONFIRM; - content.title = NULL; - content.isTouchableTitle = false; - if (page == 0) { +static void displayAddressPage(uint8_t page, bool forceFullRefresh) +{ + nbgl_pageContent_t content; + nbgl_layoutTagValue_t tagValuePair + = {.item = "Address", .value = addressConfirmationContext.address}; + + content.type = TAG_VALUE_CONFIRM; + content.title = NULL; + content.isTouchableTitle = false; + if (page == 0) { #ifdef NBGL_QRCODE - content.tagValueConfirm.detailsButtonIcon = &C_QRcode32px; - content.tagValueConfirm.detailsButtonText = "Show as QR"; - content.tagValueConfirm.detailsButtonToken = BUTTON_TOKEN; -#else // NBGL_QRCODE - content.tagValueConfirm.detailsButtonText = NULL; - content.tagValueConfirm.detailsButtonIcon = NULL; -#endif // NBGL_QRCODE - content.tagValueConfirm.tuneId = TUNE_TAP_CASUAL; - content.tagValueConfirm.tagValueList.nbPairs = 1; - content.tagValueConfirm.tagValueList.pairs = &tagValuePair; - content.tagValueConfirm.tagValueList.smallCaseForValue = false; - content.tagValueConfirm.tagValueList.nbMaxLinesForValue = 0; - content.tagValueConfirm.tagValueList.wrapping = false; - // if it's an extended address verif, it takes 2 pages, so display a "Tap to continue", and no confirmation button - if (navInfo.nbPages > 1) { - navInfo.navWithTap.nextPageText = "Tap to continue"; - content.tagValueConfirm.confirmationText = NULL; + content.tagValueConfirm.detailsButtonIcon = &C_QRcode32px; + content.tagValueConfirm.detailsButtonText = "Show as QR"; + content.tagValueConfirm.detailsButtonToken = BUTTON_TOKEN; +#else // NBGL_QRCODE + content.tagValueConfirm.detailsButtonText = NULL; + content.tagValueConfirm.detailsButtonIcon = NULL; +#endif // NBGL_QRCODE + content.tagValueConfirm.tuneId = TUNE_TAP_CASUAL; + content.tagValueConfirm.tagValueList.nbPairs = 1; + content.tagValueConfirm.tagValueList.pairs = &tagValuePair; + content.tagValueConfirm.tagValueList.smallCaseForValue = false; + content.tagValueConfirm.tagValueList.nbMaxLinesForValue = 0; + content.tagValueConfirm.tagValueList.wrapping = false; + // if it's an extended address verif, it takes 2 pages, so display a "Tap to continue", and + // no confirmation button + if (navInfo.nbPages > 1) { + navInfo.navWithTap.nextPageText = "Tap to continue"; + content.tagValueConfirm.confirmationText = NULL; + } + else { + // otherwise no tap to continue but a confirmation button + content.tagValueConfirm.confirmationText = "Confirm"; + content.tagValueConfirm.confirmationToken = CONFIRM_TOKEN; + } + } + else if (page == 1) { + // the second page is dedicated to the extended tag/value pairs + content.type = TAG_VALUE_CONFIRM; + content.tagValueConfirm.confirmationText = "Confirm"; + content.tagValueConfirm.confirmationToken = CONFIRM_TOKEN; + content.tagValueConfirm.detailsButtonText = NULL; + content.tagValueConfirm.detailsButtonIcon = NULL; + content.tagValueConfirm.tuneId = TUNE_TAP_CASUAL; + content.tagValueConfirm.tagValueList.nbPairs + = addressConfirmationContext.tagValueList->nbPairs; + content.tagValueConfirm.tagValueList.pairs = addressConfirmationContext.tagValueList->pairs; + content.tagValueConfirm.tagValueList.smallCaseForValue + = addressConfirmationContext.tagValueList->smallCaseForValue; + content.tagValueConfirm.tagValueList.nbMaxLinesForValue + = addressConfirmationContext.tagValueList->nbMaxLinesForValue; + content.tagValueConfirm.tagValueList.wrapping + = addressConfirmationContext.tagValueList->wrapping; + + // no next page + navInfo.navWithTap.nextPageText = NULL; + } + // fill navigation structure + navInfo.activePage = page; + + nbgl_pageDrawGenericContent(&pageCallback, &navInfo, &content); + + if (forceFullRefresh) { + nbgl_refreshSpecial(FULL_COLOR_CLEAN_REFRESH); } else { - // otherwise no tap to continue but a confirmation button - content.tagValueConfirm.confirmationText = "Confirm"; - content.tagValueConfirm.confirmationToken = CONFIRM_TOKEN; - } - } - else if (page == 1) { - // the second page is dedicated to the extended tag/value pairs - content.type = TAG_VALUE_CONFIRM; - content.tagValueConfirm.confirmationText = "Confirm"; - content.tagValueConfirm.confirmationToken = CONFIRM_TOKEN; - content.tagValueConfirm.detailsButtonText = NULL; - content.tagValueConfirm.detailsButtonIcon = NULL; - content.tagValueConfirm.tuneId = TUNE_TAP_CASUAL; - content.tagValueConfirm.tagValueList.nbPairs = addressConfirmationContext.tagValueList->nbPairs; - content.tagValueConfirm.tagValueList.pairs = addressConfirmationContext.tagValueList->pairs; - content.tagValueConfirm.tagValueList.smallCaseForValue = addressConfirmationContext.tagValueList->smallCaseForValue; - content.tagValueConfirm.tagValueList.nbMaxLinesForValue = addressConfirmationContext.tagValueList->nbMaxLinesForValue; - content.tagValueConfirm.tagValueList.wrapping = addressConfirmationContext.tagValueList->wrapping; - - // no next page - navInfo.navWithTap.nextPageText = NULL; - } - // fill navigation structure - navInfo.activePage = page; - - nbgl_pageDrawGenericContent(&pageCallback, &navInfo, &content); - - if (forceFullRefresh) { - nbgl_refreshSpecial(FULL_COLOR_CLEAN_REFRESH); - } else { - nbgl_refreshSpecial(FULL_COLOR_PARTIAL_REFRESH); - } + nbgl_refreshSpecial(FULL_COLOR_PARTIAL_REFRESH); + } } // called when skip button is touched in footer, during forward only review -static void displaySkipWarning(void) { - nbgl_pageConfirmationDescription_t info = { - .cancelText = "Go back to review", - .centeredInfo.text1 = "Skip message review?", - .centeredInfo.text2 = "Skip only if you trust the\nsource. If you skip, you won't\nbe able to review it again.", - .centeredInfo.text3 = NULL, - .centeredInfo.style = LARGE_CASE_INFO, - .centeredInfo.icon = &C_warning64px, - .centeredInfo.offsetY = -64, - .confirmationText = "Yes, skip", - .confirmationToken = SKIP_TOKEN, - .tuneId = TUNE_TAP_CASUAL, - .modal = true - }; - modalPageContext = nbgl_pageDrawConfirmation(&pageModalCallback, &info); - nbgl_refreshSpecial(FULL_COLOR_PARTIAL_REFRESH); +static void displaySkipWarning(void) +{ + nbgl_pageConfirmationDescription_t info = { + .cancelText = "Go back to review", + .centeredInfo.text1 = "Skip message review?", + .centeredInfo.text2 + = "Skip only if you trust the\nsource. If you skip, you won't\nbe able to review it again.", + .centeredInfo.text3 = NULL, + .centeredInfo.style = LARGE_CASE_INFO, + .centeredInfo.icon = &C_warning64px, + .centeredInfo.offsetY = -64, + .confirmationText = "Yes, skip", + .confirmationToken = SKIP_TOKEN, + .tuneId = TUNE_TAP_CASUAL, + .modal = true}; + modalPageContext = nbgl_pageDrawConfirmation(&pageModalCallback, &info); + nbgl_refreshSpecial(FULL_COLOR_PARTIAL_REFRESH); } ///////////// STATIC REVIEW UTILITIES ///////////// // sets the number of pairs fitting in the given page, with tooLongToFit param -static void setNbPairs(uint8_t page, uint8_t nbPairs, bool tooLongToFit) { - nbPairsPerPage[page/4] &= ~(3<<((page%4)*2)); - nbPairsPerPage[page/4] |= ((nbPairs-1)<<((page%4)*2)); - if (tooLongToFit) - tooLongToFitPerPage[page/8] |= 1<<(page%8); - else - tooLongToFitPerPage[page/8] &= ~(1<<(page%8)); +static void setNbPairs(uint8_t page, uint8_t nbPairs, bool tooLongToFit) +{ + nbPairsPerPage[page / 4] &= ~(3 << ((page % 4) * 2)); + nbPairsPerPage[page / 4] |= ((nbPairs - 1) << ((page % 4) * 2)); + if (tooLongToFit) { + tooLongToFitPerPage[page / 8] |= 1 << (page % 8); + } + else { + tooLongToFitPerPage[page / 8] &= ~(1 << (page % 8)); + } } -// returns the number of pairs fitting in the given page, setting tooLongToFit at the appropriate value -static uint8_t getNbPairs(uint8_t page, bool *tooLongToFit) { - uint8_t nbPairs = (nbPairsPerPage[page/4] >> ((page%4)*2))&3; - *tooLongToFit = (tooLongToFitPerPage[page/8] & (1<<(page%8)))?true:false; - return nbPairs+1; +// returns the number of pairs fitting in the given page, setting tooLongToFit at the appropriate +// value +static uint8_t getNbPairs(uint8_t page, bool *tooLongToFit) +{ + uint8_t nbPairs = (nbPairsPerPage[page / 4] >> ((page % 4) * 2)) & 3; + *tooLongToFit = (tooLongToFitPerPage[page / 8] & (1 << (page % 8))) ? true : false; + return nbPairs + 1; } /********************** @@ -636,7 +686,8 @@ static uint8_t getNbPairs(uint8_t page, bool *tooLongToFit) { **********************/ /** - * @brief computes the number of tag/values pairs displayable in a page, with the given list of tag/value pairs + * @brief computes the number of tag/values pairs displayable in a page, with the given list of + * tag/value pairs * * @param nbPairs number of tag/value pairs to use in \b tagValueList * @param tagValueList list of tag/value pairs @@ -644,55 +695,61 @@ static uint8_t getNbPairs(uint8_t page, bool *tooLongToFit) { * @param tooLongToFit (output) set to true if even a single tag/value pair doesn't fit in a page * @return the number of tag/value pairs fitting in a page */ -uint8_t nbgl_useCaseGetNbTagValuesInPage(uint8_t nbPairs, - const nbgl_layoutTagValueList_t *tagValueList, - uint8_t startIndex, - bool *tooLongToFit) { - uint8_t nbPairsInPage = 0; - uint16_t currentHeight = 12; // upper margin - - *tooLongToFit = false; - while (nbPairsInPage < nbPairs) { - const char *item; - const char *value; - nbgl_layoutTagValue_t* callback_result; - nbgl_font_id_e value_font; - // margin between pairs - if (nbPairsInPage>0) - currentHeight += 12; - // fetch tag/value pair strings. - if (tagValueList->pairs != NULL) { - value = tagValueList->pairs[startIndex+nbPairsInPage].value; - item = tagValueList->pairs[startIndex+nbPairsInPage].item; +uint8_t nbgl_useCaseGetNbTagValuesInPage(uint8_t nbPairs, + const nbgl_layoutTagValueList_t *tagValueList, + uint8_t startIndex, + bool *tooLongToFit) +{ + uint8_t nbPairsInPage = 0; + uint16_t currentHeight = 12; // upper margin + + *tooLongToFit = false; + while (nbPairsInPage < nbPairs) { + const char *item; + const char *value; + nbgl_layoutTagValue_t *callback_result; + nbgl_font_id_e value_font; + // margin between pairs + if (nbPairsInPage > 0) { + currentHeight += 12; + } + // fetch tag/value pair strings. + if (tagValueList->pairs != NULL) { + value = tagValueList->pairs[startIndex + nbPairsInPage].value; + item = tagValueList->pairs[startIndex + nbPairsInPage].item; + } + else { + callback_result = tagValueList->callback(startIndex + nbPairsInPage); + value = callback_result->value; + item = callback_result->item; + } + // tag height + currentHeight += nbgl_getTextHeightInWidth(BAGL_FONT_INTER_REGULAR_24px, + item, + SCREEN_WIDTH - 2 * BORDER_MARGIN, + tagValueList->wrapping); + // space between tag and value + currentHeight += 4; + // set value font + if (tagValueList->smallCaseForValue) { + value_font = BAGL_FONT_INTER_REGULAR_24px; + } + else { + value_font = BAGL_FONT_INTER_MEDIUM_32px; + } + // value height + currentHeight += nbgl_getTextHeightInWidth( + value_font, value, SCREEN_WIDTH - 2 * BORDER_MARGIN, tagValueList->wrapping); + if (currentHeight >= TAG_VALUE_AREA_HEIGHT) { + break; + } + nbPairsInPage++; } - else { - callback_result = tagValueList->callback(startIndex+nbPairsInPage); - value = callback_result->value; - item = callback_result->item; - } - // tag height - currentHeight += nbgl_getTextHeightInWidth(BAGL_FONT_INTER_REGULAR_24px, - item,SCREEN_WIDTH-2*BORDER_MARGIN, tagValueList->wrapping); - // space between tag and value - currentHeight += 4; - // set value font - if (tagValueList->smallCaseForValue) { - value_font = BAGL_FONT_INTER_REGULAR_24px; - } else { - value_font = BAGL_FONT_INTER_MEDIUM_32px; - } - // value height - currentHeight += nbgl_getTextHeightInWidth(value_font, - value,SCREEN_WIDTH-2*BORDER_MARGIN, tagValueList->wrapping); - if (currentHeight >= TAG_VALUE_AREA_HEIGHT) - break; - nbPairsInPage++; - } - if ((nbPairsInPage == 0)&&(currentHeight>=TAG_VALUE_AREA_HEIGHT)) { - *tooLongToFit = true; - nbPairsInPage = 1; - } - return nbPairsInPage; + if ((nbPairsInPage == 0) && (currentHeight >= TAG_VALUE_AREA_HEIGHT)) { + *tooLongToFit = true; + nbPairsInPage = 1; + } + return nbPairsInPage; } /** @@ -701,24 +758,25 @@ uint8_t nbgl_useCaseGetNbTagValuesInPage(uint8_t nbPairs, * @param tagValueList list of tag/value pairs * @return the number of pages necessary to display the given list of tag/value pairs */ -uint8_t nbgl_useCaseGetNbPagesForTagValueList(const nbgl_layoutTagValueList_t *tagValueList) { - uint8_t nbPages = 0; - uint8_t nbPairs = tagValueList->nbPairs; - uint8_t nbPairsInPage; - uint16_t currentHeight = 0; - uint8_t i=0; - bool tooLongToFit; - - while (i < tagValueList->nbPairs) { - // upper margin - currentHeight += 24; - nbPairsInPage = nbgl_useCaseGetNbTagValuesInPage(nbPairs, tagValueList, i, &tooLongToFit); - i += nbPairsInPage; - setNbPairs(nbPages,nbPairsInPage,tooLongToFit); - nbPairs -= nbPairsInPage; - nbPages++; - } - return nbPages; +uint8_t nbgl_useCaseGetNbPagesForTagValueList(const nbgl_layoutTagValueList_t *tagValueList) +{ + uint8_t nbPages = 0; + uint8_t nbPairs = tagValueList->nbPairs; + uint8_t nbPairsInPage; + uint16_t currentHeight = 0; + uint8_t i = 0; + bool tooLongToFit; + + while (i < tagValueList->nbPairs) { + // upper margin + currentHeight += 24; + nbPairsInPage = nbgl_useCaseGetNbTagValuesInPage(nbPairs, tagValueList, i, &tooLongToFit); + i += nbPairsInPage; + setNbPairs(nbPages, nbPairsInPage, tooLongToFit); + nbPairs -= nbPairsInPage; + nbPages++; + } + return nbPages; } /** @@ -726,138 +784,182 @@ uint8_t nbgl_useCaseGetNbPagesForTagValueList(const nbgl_layoutTagValueList_t *t * * @param appName app name * @param appIcon app icon - * @param tagline text under app name (if NULL, it will be "This app enables signing transactions on the network.") - * @param withSettings if true, use a "settings" (wheel) icon in bottom button, otherwise a "info" (i) + * @param tagline text under app name (if NULL, it will be "This app enables signing transactions on + * the network.") + * @param withSettings if true, use a "settings" (wheel) icon in bottom button, otherwise a "info" + * (i) * @param topRightCallback callback called when top-right button is touched * @param quitCallback callback called when quit button is touched */ -void nbgl_useCaseHome(const char *appName, const nbgl_icon_details_t *appIcon, const char *tagline, bool withSettings, - nbgl_callback_t topRightCallback, nbgl_callback_t quitCallback) { - nbgl_useCaseHomeExt(appName, appIcon, tagline, withSettings, NULL, NULL, - topRightCallback, quitCallback); +void nbgl_useCaseHome(const char *appName, + const nbgl_icon_details_t *appIcon, + const char *tagline, + bool withSettings, + nbgl_callback_t topRightCallback, + nbgl_callback_t quitCallback) +{ + nbgl_useCaseHomeExt( + appName, appIcon, tagline, withSettings, NULL, NULL, topRightCallback, quitCallback); } /** - * @brief draws the extended version of home page of an app (page on which we land when launching it from dashboard) + * @brief draws the extended version of home page of an app (page on which we land when launching it + * from dashboard) * @note it enables to use an action button (black) * * @param appName app name * @param appIcon app icon - * @param tagline text under app name (if NULL, it will be "This app enables signing transactions on the network.") - * @param withSettings if true, use a "settings" (wheel) icon in bottom button, otherwise a "info" (i) - * @param actionButtonText if not NULL, text used for an action button (in black, on top of "Quit App" button) - * @param actionCallback callback called when action button is touched (if actionButtonText is not NULL) + * @param tagline text under app name (if NULL, it will be "This app enables signing transactions on + * the network.") + * @param withSettings if true, use a "settings" (wheel) icon in bottom button, otherwise a "info" + * (i) + * @param actionButtonText if not NULL, text used for an action button (in black, on top of "Quit + * App" button) + * @param actionCallback callback called when action button is touched (if actionButtonText is not + * NULL) * @param topRightCallback callback called when top-right button is touched * @param quitCallback callback called when quit button is touched */ -void nbgl_useCaseHomeExt(const char *appName, const nbgl_icon_details_t *appIcon, const char *tagline, bool withSettings, - const char *actionButtonText, nbgl_callback_t actionCallback, - nbgl_callback_t topRightCallback, nbgl_callback_t quitCallback) { - nbgl_pageInfoDescription_t info = { - .centeredInfo.icon = appIcon, - .centeredInfo.text1 = appName, - .centeredInfo.text3 = NULL, - .centeredInfo.style = LARGE_CASE_INFO, - .centeredInfo.offsetY = -16, - .footerText = NULL, - .bottomButtonStyle = QUIT_APP_TEXT, - .tapActionText = NULL, - .topRightStyle = withSettings? SETTINGS_ICON:INFO_ICON, - .topRightToken = CONTINUE_TOKEN, - .actionButtonText = actionButtonText, - .tuneId = TUNE_TAP_CASUAL - }; - if (actionButtonText != NULL) { - // trick to use ACTION_BUTTON_TOKEN for action and quit, with index used to distinguish - info.bottomButtonsToken = ACTION_BUTTON_TOKEN; - onAction = actionCallback; - } - else { - info.bottomButtonsToken = QUIT_TOKEN; - onAction = actionCallback; - } - if (tagline == NULL) { - if (strlen(appName) > MAX_APP_NAME_FOR_SDK_TAGLINE) { - snprintf(appDescription, APP_DESCRIPTION_MAX_LEN, "This app enables signing\ntransactions on its network."); - } - else { - snprintf(appDescription, APP_DESCRIPTION_MAX_LEN, "%s %s\n%s", TAGLINE_PART1, appName, TAGLINE_PART2); - } - - // If there is more than 3 lines, it means the appName was split, so we put it on the next line - if (nbgl_getTextNbLinesInWidth(BAGL_FONT_INTER_REGULAR_24px, appDescription, SCREEN_WIDTH-2*BORDER_MARGIN, false) > 3) { - snprintf(appDescription, APP_DESCRIPTION_MAX_LEN, "%s\n%s %s", TAGLINE_PART1, appName, TAGLINE_PART2); - } - info.centeredInfo.text2 = appDescription; - } - else { - info.centeredInfo.text2 = tagline; - } - - onContinue = topRightCallback; - onQuit = quitCallback; - if (actionButtonText != NULL) { - info.centeredInfo.offsetY -= 40; - } - pageContext = nbgl_pageDrawInfo(&pageCallback, NULL, &info); - nbgl_refreshSpecial(FULL_COLOR_CLEAN_REFRESH); +void nbgl_useCaseHomeExt(const char *appName, + const nbgl_icon_details_t *appIcon, + const char *tagline, + bool withSettings, + const char *actionButtonText, + nbgl_callback_t actionCallback, + nbgl_callback_t topRightCallback, + nbgl_callback_t quitCallback) +{ + nbgl_pageInfoDescription_t info = {.centeredInfo.icon = appIcon, + .centeredInfo.text1 = appName, + .centeredInfo.text3 = NULL, + .centeredInfo.style = LARGE_CASE_INFO, + .centeredInfo.offsetY = -16, + .footerText = NULL, + .bottomButtonStyle = QUIT_APP_TEXT, + .tapActionText = NULL, + .topRightStyle = withSettings ? SETTINGS_ICON : INFO_ICON, + .topRightToken = CONTINUE_TOKEN, + .actionButtonText = actionButtonText, + .tuneId = TUNE_TAP_CASUAL}; + if (actionButtonText != NULL) { + // trick to use ACTION_BUTTON_TOKEN for action and quit, with index used to distinguish + info.bottomButtonsToken = ACTION_BUTTON_TOKEN; + onAction = actionCallback; + } + else { + info.bottomButtonsToken = QUIT_TOKEN; + onAction = actionCallback; + } + if (tagline == NULL) { + if (strlen(appName) > MAX_APP_NAME_FOR_SDK_TAGLINE) { + snprintf(appDescription, + APP_DESCRIPTION_MAX_LEN, + "This app enables signing\ntransactions on its network."); + } + else { + snprintf(appDescription, + APP_DESCRIPTION_MAX_LEN, + "%s %s\n%s", + TAGLINE_PART1, + appName, + TAGLINE_PART2); + } + + // If there is more than 3 lines, it means the appName was split, so we put it on the next + // line + if (nbgl_getTextNbLinesInWidth(BAGL_FONT_INTER_REGULAR_24px, + appDescription, + SCREEN_WIDTH - 2 * BORDER_MARGIN, + false) + > 3) { + snprintf(appDescription, + APP_DESCRIPTION_MAX_LEN, + "%s\n%s %s", + TAGLINE_PART1, + appName, + TAGLINE_PART2); + } + info.centeredInfo.text2 = appDescription; + } + else { + info.centeredInfo.text2 = tagline; + } + + onContinue = topRightCallback; + onQuit = quitCallback; + if (actionButtonText != NULL) { + info.centeredInfo.offsetY -= 40; + } + pageContext = nbgl_pageDrawInfo(&pageCallback, NULL, &info); + nbgl_refreshSpecial(FULL_COLOR_CLEAN_REFRESH); } /** - * @brief draws the home page of a plug-in app (page on which we land when launching it from dashboard) + * @brief draws the home page of a plug-in app (page on which we land when launching it from + * dashboard) * * @param plugInName plug-in app name * @param appName master app name (app used by plug-in) * @param appIcon master app icon - * @param tagline text under plug-in name (if NULL, it will be "This app confirms actions for\n.") - * @param subTagline text under master app icon (if NULL, it will be "This app relies on\n") - * @param withSettings if true, use a "settings" (wheel) icon in bottom button, otherwise a "info" (i) + * @param tagline text under plug-in name (if NULL, it will be "This app confirms actions + * for\n.") + * @param subTagline text under master app icon (if NULL, it will be "This app relies + * on\n") + * @param withSettings if true, use a "settings" (wheel) icon in bottom button, otherwise a "info" + * (i) * @param topRightCallback callback called when top-right button is touched * @param quitCallback callback called when quit button is touched */ -void nbgl_useCasePlugInHome(const char *plugInName, const char *appName, - const nbgl_icon_details_t *appIcon, const char *tagline, - const char *subTagline, bool withSettings, - nbgl_callback_t topRightCallback, nbgl_callback_t quitCallback) { - nbgl_pageInfoDescription_t info = { - .centeredInfo.icon = appIcon, - .centeredInfo.text1 = plugInName, - .centeredInfo.style = PLUGIN_INFO, - .centeredInfo.offsetY = -16, - .footerText = NULL, - .bottomButtonStyle = QUIT_APP_TEXT, - .tapActionText = NULL, - .topRightStyle = withSettings? SETTINGS_ICON:INFO_ICON, - .topRightToken = CONTINUE_TOKEN, - .actionButtonText = NULL, - .tuneId = TUNE_TAP_CASUAL - }; - info.bottomButtonsToken = QUIT_TOKEN; - onAction = NULL; - if (tagline == NULL) { - snprintf(appDescription, APP_DESCRIPTION_MAX_LEN, "This app confirms actions for\n%s.", plugInName); - info.centeredInfo.text2 = appDescription; - } - else { - info.centeredInfo.text2 = tagline; - } - if (subTagline == NULL) { - snprintf(plugInDescription, APP_DESCRIPTION_MAX_LEN, "This app relies on\n%s", appName); - info.centeredInfo.text3 = plugInDescription; - } - else { - info.centeredInfo.text3 = subTagline; - } - - onContinue = topRightCallback; - onQuit = quitCallback; - pageContext = nbgl_pageDrawInfo(&pageCallback, NULL, &info); - nbgl_refresh(); +void nbgl_useCasePlugInHome(const char *plugInName, + const char *appName, + const nbgl_icon_details_t *appIcon, + const char *tagline, + const char *subTagline, + bool withSettings, + nbgl_callback_t topRightCallback, + nbgl_callback_t quitCallback) +{ + nbgl_pageInfoDescription_t info = {.centeredInfo.icon = appIcon, + .centeredInfo.text1 = plugInName, + .centeredInfo.style = PLUGIN_INFO, + .centeredInfo.offsetY = -16, + .footerText = NULL, + .bottomButtonStyle = QUIT_APP_TEXT, + .tapActionText = NULL, + .topRightStyle = withSettings ? SETTINGS_ICON : INFO_ICON, + .topRightToken = CONTINUE_TOKEN, + .actionButtonText = NULL, + .tuneId = TUNE_TAP_CASUAL}; + info.bottomButtonsToken = QUIT_TOKEN; + onAction = NULL; + if (tagline == NULL) { + snprintf(appDescription, + APP_DESCRIPTION_MAX_LEN, + "This app confirms actions for\n%s.", + plugInName); + info.centeredInfo.text2 = appDescription; + } + else { + info.centeredInfo.text2 = tagline; + } + if (subTagline == NULL) { + snprintf(plugInDescription, APP_DESCRIPTION_MAX_LEN, "This app relies on\n%s", appName); + info.centeredInfo.text3 = plugInDescription; + } + else { + info.centeredInfo.text3 = subTagline; + } + + onContinue = topRightCallback; + onQuit = quitCallback; + pageContext = nbgl_pageDrawInfo(&pageCallback, NULL, &info); + nbgl_refresh(); } /** * @brief Draws the settings pages of an app with as many pages as given - * For each page, the given navCallback will be called to get the content. Only 'type' and union has to be set in this content + * For each page, the given navCallback will be called to get the content. Only 'type' and + * union has to be set in this content * * @param title string to set in touchable (or not) title * @param initPage page on which to start [0->(nbPages-1)] @@ -865,34 +967,40 @@ void nbgl_useCasePlugInHome(const char *plugInName, const char *appName, * @param touchable if true, the title is used to quit and quitCallback is called * @param quitCallback callback called when quit button (or title) is pressed * @param navCallback callback called when navigation arrows are pressed - * @param controlsCallback callback called when any controls in the settings (radios, switches) is called (the tokens must be >= @ref FIRST_USER_TOKEN) + * @param controlsCallback callback called when any controls in the settings (radios, switches) is + * called (the tokens must be >= @ref FIRST_USER_TOKEN) */ -void nbgl_useCaseSettings(const char *title, uint8_t initPage, uint8_t nbPages, bool touchable, - nbgl_callback_t quitCallback, nbgl_navCallback_t navCallback, - nbgl_layoutTouchCallback_t controlsCallback) { - // memorize context - onQuit = quitCallback; - onNav = navCallback; - onControls = controlsCallback; - settingsTitle = title; - touchableTitle = touchable; - - // fill navigation structure - navInfo.activePage = initPage; - navInfo.navType = NAV_WITH_BUTTONS; - navInfo.navWithButtons.navToken = NAV_TOKEN; - if (!touchableTitle) { - navInfo.navWithButtons.quitButton = true; - navInfo.quitToken = QUIT_TOKEN; - } - else { - navInfo.navWithButtons.quitButton = false; - } - navInfo.nbPages = nbPages; - navInfo.progressIndicator = false; - navInfo.tuneId = TUNE_TAP_CASUAL; - - displaySettingsPage(navInfo.activePage, true); +void nbgl_useCaseSettings(const char *title, + uint8_t initPage, + uint8_t nbPages, + bool touchable, + nbgl_callback_t quitCallback, + nbgl_navCallback_t navCallback, + nbgl_layoutTouchCallback_t controlsCallback) +{ + // memorize context + onQuit = quitCallback; + onNav = navCallback; + onControls = controlsCallback; + settingsTitle = title; + touchableTitle = touchable; + + // fill navigation structure + navInfo.activePage = initPage; + navInfo.navType = NAV_WITH_BUTTONS; + navInfo.navWithButtons.navToken = NAV_TOKEN; + if (!touchableTitle) { + navInfo.navWithButtons.quitButton = true; + navInfo.quitToken = QUIT_TOKEN; + } + else { + navInfo.navWithButtons.quitButton = false; + } + navInfo.nbPages = nbPages; + navInfo.progressIndicator = false; + navInfo.tuneId = TUNE_TAP_CASUAL; + + displaySettingsPage(navInfo.activePage, true); } /** @@ -902,45 +1010,45 @@ void nbgl_useCaseSettings(const char *title, uint8_t initPage, uint8_t nbPages, * @param isSuccess if true, message is drawn in a Ledger style (with corners) * @param quitCallback callback called when quit timer times out */ -void nbgl_useCaseStatus(const char *message, bool isSuccess, nbgl_callback_t quitCallback) { - nbgl_screenTickerConfiguration_t ticker = { - .tickerCallback = &tickerCallback, - .tickerIntervale = 0, // not periodic - .tickerValue = 3000 // 3 seconds - }; - onQuit = quitCallback; - if (isSuccess) { -#ifdef HAVE_PIEZO_SOUND - io_seproxyhal_play_tune(TUNE_LEDGER_MOMENT); -#endif // HAVE_PIEZO_SOUND - - pageContext = nbgl_pageDrawLedgerInfo(&pageCallback, &ticker, message, QUIT_TOKEN); - } - else { - nbgl_pageInfoDescription_t info = { - .bottomButtonStyle = NO_BUTTON_STYLE, - .footerText = NULL, - .centeredInfo.icon = &C_round_cross_64px, - .centeredInfo.offsetY = 0, - .centeredInfo.onTop = false, - .centeredInfo.style = LARGE_CASE_INFO, - .centeredInfo.text1 = message, - .centeredInfo.text2 = NULL, - .centeredInfo.text3 = NULL, - .tapActionText = "", - .tapActionToken = QUIT_TOKEN, - .topRightStyle = NO_BUTTON_STYLE, - .actionButtonText = NULL, - .tuneId = TUNE_TAP_CASUAL +void nbgl_useCaseStatus(const char *message, bool isSuccess, nbgl_callback_t quitCallback) +{ + nbgl_screenTickerConfiguration_t ticker = { + .tickerCallback = &tickerCallback, + .tickerIntervale = 0, // not periodic + .tickerValue = 3000 // 3 seconds }; - pageContext = nbgl_pageDrawInfo(&pageCallback, &ticker,&info); - } - nbgl_refreshSpecial(FULL_COLOR_PARTIAL_REFRESH); + onQuit = quitCallback; + if (isSuccess) { +#ifdef HAVE_PIEZO_SOUND + io_seproxyhal_play_tune(TUNE_LEDGER_MOMENT); +#endif // HAVE_PIEZO_SOUND + + pageContext = nbgl_pageDrawLedgerInfo(&pageCallback, &ticker, message, QUIT_TOKEN); + } + else { + nbgl_pageInfoDescription_t info = {.bottomButtonStyle = NO_BUTTON_STYLE, + .footerText = NULL, + .centeredInfo.icon = &C_round_cross_64px, + .centeredInfo.offsetY = 0, + .centeredInfo.onTop = false, + .centeredInfo.style = LARGE_CASE_INFO, + .centeredInfo.text1 = message, + .centeredInfo.text2 = NULL, + .centeredInfo.text3 = NULL, + .tapActionText = "", + .tapActionToken = QUIT_TOKEN, + .topRightStyle = NO_BUTTON_STYLE, + .actionButtonText = NULL, + .tuneId = TUNE_TAP_CASUAL}; + pageContext = nbgl_pageDrawInfo(&pageCallback, &ticker, &info); + } + nbgl_refreshSpecial(FULL_COLOR_PARTIAL_REFRESH); } /** - * @brief Draws a generic choice page, described in a centered info (with configurable icon), thanks to a button and a footer - * at the bottom of the page. The given callback is called with true as argument if the button is touched, false if footer is touched + * @brief Draws a generic choice page, described in a centered info (with configurable icon), thanks + * to a button and a footer at the bottom of the page. The given callback is called with true as + * argument if the button is touched, false if footer is touched * * @param icon icon to set in center of page * @param message string to set in center of page (32px) @@ -949,33 +1057,39 @@ void nbgl_useCaseStatus(const char *message, bool isSuccess, nbgl_callback_t qui * @param cancelText string to set in footer, to reject (cannot be NULL) * @param callback callback called when button or footer is touched */ -void nbgl_useCaseChoice(const nbgl_icon_details_t *icon, const char *message, const char *subMessage, const char *confirmText, const char *cancelText, nbgl_choiceCallback_t callback) { - nbgl_pageConfirmationDescription_t info = { - .cancelText = cancelText, - .centeredInfo.text1 = message, - .centeredInfo.text2 = subMessage, - .centeredInfo.text3 = NULL, - .centeredInfo.style = LARGE_CASE_INFO, - .centeredInfo.icon = icon, - .centeredInfo.offsetY = -40, - .confirmationText = confirmText, - .confirmationToken = CHOICE_TOKEN, - .tuneId = TUNE_TAP_CASUAL, - .modal = false - }; - // check params - if ((confirmText == NULL) || (cancelText == NULL)) { - return; - } - onChoice = callback; - pageContext = nbgl_pageDrawConfirmation(&pageCallback, &info); - nbgl_refreshSpecial(FULL_COLOR_PARTIAL_REFRESH); +void nbgl_useCaseChoice(const nbgl_icon_details_t *icon, + const char *message, + const char *subMessage, + const char *confirmText, + const char *cancelText, + nbgl_choiceCallback_t callback) +{ + nbgl_pageConfirmationDescription_t info = {.cancelText = cancelText, + .centeredInfo.text1 = message, + .centeredInfo.text2 = subMessage, + .centeredInfo.text3 = NULL, + .centeredInfo.style = LARGE_CASE_INFO, + .centeredInfo.icon = icon, + .centeredInfo.offsetY = -40, + .confirmationText = confirmText, + .confirmationToken = CHOICE_TOKEN, + .tuneId = TUNE_TAP_CASUAL, + .modal = false}; + // check params + if ((confirmText == NULL) || (cancelText == NULL)) { + return; + } + onChoice = callback; + pageContext = nbgl_pageDrawConfirmation(&pageCallback, &info); + nbgl_refreshSpecial(FULL_COLOR_PARTIAL_REFRESH); } /** - * @brief Draws a page to confirm or not an action, described in a centered info (with info icon), thanks to a button and a footer - * at the bottom of the page. The given callback is called if the button is touched. If the footer is touched, the page is only "dismissed" - * @note This page is displayed as a modal (so the content of the previous page will be visible when dismissed). + * @brief Draws a page to confirm or not an action, described in a centered info (with info icon), + * thanks to a button and a footer at the bottom of the page. The given callback is called if the + * button is touched. If the footer is touched, the page is only "dismissed" + * @note This page is displayed as a modal (so the content of the previous page will be visible when + * dismissed). * * @param message string to set in center of page (32px) * @param subMessage string to set under message (24px) (can be NULL) @@ -983,27 +1097,31 @@ void nbgl_useCaseChoice(const nbgl_icon_details_t *icon, const char *message, co * @param cancelText string to set in footer, to reject * @param callback callback called when confirmation button is touched */ -void nbgl_useCaseConfirm(const char *message, const char *subMessage, const char *confirmText, const char *cancelText, nbgl_callback_t callback) { - nbgl_pageConfirmationDescription_t info = { - .cancelText = cancelText, - .centeredInfo.text1 = message, - .centeredInfo.text2 = subMessage, - .centeredInfo.text3 = NULL, - .centeredInfo.style = LARGE_CASE_INFO, - .centeredInfo.icon = &C_round_warning_64px, - .centeredInfo.offsetY = -40, - .confirmationText = confirmText, - .confirmationToken = CHOICE_TOKEN, - .tuneId = TUNE_TAP_CASUAL, - .modal = true - }; - onModalConfirm = callback; - modalPageContext = nbgl_pageDrawConfirmation(&pageModalCallback, &info); - nbgl_refreshSpecial(FULL_COLOR_PARTIAL_REFRESH); +void nbgl_useCaseConfirm(const char *message, + const char *subMessage, + const char *confirmText, + const char *cancelText, + nbgl_callback_t callback) +{ + nbgl_pageConfirmationDescription_t info = {.cancelText = cancelText, + .centeredInfo.text1 = message, + .centeredInfo.text2 = subMessage, + .centeredInfo.text3 = NULL, + .centeredInfo.style = LARGE_CASE_INFO, + .centeredInfo.icon = &C_round_warning_64px, + .centeredInfo.offsetY = -40, + .confirmationText = confirmText, + .confirmationToken = CHOICE_TOKEN, + .tuneId = TUNE_TAP_CASUAL, + .modal = true}; + onModalConfirm = callback; + modalPageContext = nbgl_pageDrawConfirmation(&pageModalCallback, &info); + nbgl_refreshSpecial(FULL_COLOR_PARTIAL_REFRESH); } /** - * @brief Draws a review start page, with a centered message, a "tap to continue" container and a "reject" footer + * @brief Draws a review start page, with a centered message, a "tap to continue" container and a + * "reject" footer * * @param icon icon to use in centered info * @param reviewTitle string to set in middle of page (in 32px font) @@ -1012,262 +1130,302 @@ void nbgl_useCaseConfirm(const char *message, const char *subMessage, const char * @param continueCallback callback called when main panel is touched * @param rejectCallback callback called when footer is touched */ -void nbgl_useCaseReviewStart(const nbgl_icon_details_t *icon, const char *reviewTitle, const char *reviewSubTitle, const char *rejectText, - nbgl_callback_t continueCallback, nbgl_callback_t rejectCallback) { - nbgl_pageInfoDescription_t info = { - .centeredInfo.icon = icon, - .centeredInfo.text1 = reviewTitle, - .centeredInfo.text2 = reviewSubTitle, - .centeredInfo.text3 = NULL, - .centeredInfo.style = LARGE_CASE_INFO, - .centeredInfo.offsetY = 0, - .footerText = rejectText, - .footerToken = QUIT_TOKEN, - .tapActionText = "Tap to continue", - .tapActionToken = CONTINUE_TOKEN, - .topRightStyle = NO_BUTTON_STYLE, - .actionButtonText = NULL, - .tuneId = TUNE_TAP_CASUAL - }; - onQuit = rejectCallback; - onContinue = continueCallback; +void nbgl_useCaseReviewStart(const nbgl_icon_details_t *icon, + const char *reviewTitle, + const char *reviewSubTitle, + const char *rejectText, + nbgl_callback_t continueCallback, + nbgl_callback_t rejectCallback) +{ + nbgl_pageInfoDescription_t info = {.centeredInfo.icon = icon, + .centeredInfo.text1 = reviewTitle, + .centeredInfo.text2 = reviewSubTitle, + .centeredInfo.text3 = NULL, + .centeredInfo.style = LARGE_CASE_INFO, + .centeredInfo.offsetY = 0, + .footerText = rejectText, + .footerToken = QUIT_TOKEN, + .tapActionText = "Tap to continue", + .tapActionToken = CONTINUE_TOKEN, + .topRightStyle = NO_BUTTON_STYLE, + .actionButtonText = NULL, + .tuneId = TUNE_TAP_CASUAL}; + onQuit = rejectCallback; + onContinue = continueCallback; #ifdef HAVE_PIEZO_SOUND - // Play notification sound - io_seproxyhal_play_tune(TUNE_LOOK_AT_ME); -#endif // HAVE_PIEZO_SOUND + // Play notification sound + io_seproxyhal_play_tune(TUNE_LOOK_AT_ME); +#endif // HAVE_PIEZO_SOUND - pageContext = nbgl_pageDrawInfo(&pageCallback, NULL, &info); - nbgl_refresh(); + pageContext = nbgl_pageDrawInfo(&pageCallback, NULL, &info); + nbgl_refresh(); } /** - * @brief Draws a flow of pages of a review. A back key is available on top-left of the screen, except in first page - * It is possible to go to next page thanks to "tap to continue". - * For each page, the given navCallback will be called to get the content. Only 'type' and union has to be set in this content + * @brief Draws a flow of pages of a review. A back key is available on top-left of the screen, + * except in first page It is possible to go to next page thanks to "tap to continue". For each + * page, the given navCallback will be called to get the content. Only 'type' and union has to be + * set in this content * * @param initPage page on which to start [0->(nbPages-1)] * @param nbPages number of pages. If 0, no progress indicator is used * @param rejectText text to use in footer * @param navCallback callback called when navigation (back or "tap to continue") is touched * @param buttonCallback callback called when a potential button (details) in the content is touched - * @param choiceCallback callback called when either long_press or footer is called (param is true for long press) + * @param choiceCallback callback called when either long_press or footer is called (param is true + * for long press) */ -void nbgl_useCaseRegularReview(uint8_t initPage, uint8_t nbPages, const char *rejectText, nbgl_layoutTouchCallback_t buttonCallback, - nbgl_navCallback_t navCallback, nbgl_choiceCallback_t choiceCallback) { - // memorize context - onChoice = choiceCallback; - onNav = navCallback; - onControls = buttonCallback; - forwardNavOnly = false; - - // fill navigation structure - navInfo.nbPages = nbPages; - navInfo.navType = NAV_WITH_TAP; - navInfo.quitToken = REJECT_TOKEN; - navInfo.navWithTap.nextPageToken = NEXT_TOKEN; - navInfo.navWithTap.quitText = rejectText; - navInfo.navWithTap.backToken = BACK_TOKEN; - navInfo.navWithTap.skipText = NULL; - navInfo.progressIndicator = true; - navInfo.tuneId = TUNE_TAP_CASUAL; - - displayReviewPage(initPage, true); +void nbgl_useCaseRegularReview(uint8_t initPage, + uint8_t nbPages, + const char *rejectText, + nbgl_layoutTouchCallback_t buttonCallback, + nbgl_navCallback_t navCallback, + nbgl_choiceCallback_t choiceCallback) +{ + // memorize context + onChoice = choiceCallback; + onNav = navCallback; + onControls = buttonCallback; + forwardNavOnly = false; + + // fill navigation structure + navInfo.nbPages = nbPages; + navInfo.navType = NAV_WITH_TAP; + navInfo.quitToken = REJECT_TOKEN; + navInfo.navWithTap.nextPageToken = NEXT_TOKEN; + navInfo.navWithTap.quitText = rejectText; + navInfo.navWithTap.backToken = BACK_TOKEN; + navInfo.navWithTap.skipText = NULL; + navInfo.progressIndicator = true; + navInfo.tuneId = TUNE_TAP_CASUAL; + + displayReviewPage(initPage, true); } /** * @brief Draws a flow of pages of a review, without back key. * It is possible to go to next page thanks to "tap to continue". - * For each page, the given navCallback will be called to get the content. Only 'type' and union has to be set in this content + * For each page, the given navCallback will be called to get the content. Only 'type' and + * union has to be set in this content * * @param rejectText text to use in footer - * @param buttonCallback callback called when a potential button (details or long press) in the content is touched - * @param navCallback callback called when navigation "tap to continue" is touched, to get the content of next page - * @param choiceCallback callback called when either long_press or footer is called (param is true for long press) + * @param buttonCallback callback called when a potential button (details or long press) in the + * content is touched + * @param navCallback callback called when navigation "tap to continue" is touched, to get the + * content of next page + * @param choiceCallback callback called when either long_press or footer is called (param is true + * for long press) */ -void nbgl_useCaseForwardOnlyReview(const char *rejectText, nbgl_layoutTouchCallback_t buttonCallback, - nbgl_navCallback_t navCallback, nbgl_choiceCallback_t choiceCallback) { - // memorize context - onChoice = choiceCallback; - onNav = navCallback; - onControls = buttonCallback; - forwardNavOnly = true; - - // fill navigation structure - navInfo.nbPages = 0; - navInfo.navType = NAV_WITH_TAP; - navInfo.quitToken = QUIT_TOKEN; - navInfo.navWithTap.nextPageToken = NEXT_TOKEN; - navInfo.navWithTap.quitText = rejectText; - navInfo.navWithTap.backToken = BACK_TOKEN; - navInfo.navWithTap.skipText = "Skip >>"; - navInfo.navWithTap.skipToken = SKIP_TOKEN; - navInfo.progressIndicator = true; - navInfo.tuneId = TUNE_TAP_CASUAL; - - displayReviewPage(0, false); +void nbgl_useCaseForwardOnlyReview(const char *rejectText, + nbgl_layoutTouchCallback_t buttonCallback, + nbgl_navCallback_t navCallback, + nbgl_choiceCallback_t choiceCallback) +{ + // memorize context + onChoice = choiceCallback; + onNav = navCallback; + onControls = buttonCallback; + forwardNavOnly = true; + + // fill navigation structure + navInfo.nbPages = 0; + navInfo.navType = NAV_WITH_TAP; + navInfo.quitToken = QUIT_TOKEN; + navInfo.navWithTap.nextPageToken = NEXT_TOKEN; + navInfo.navWithTap.quitText = rejectText; + navInfo.navWithTap.backToken = BACK_TOKEN; + navInfo.navWithTap.skipText = "Skip >>"; + navInfo.navWithTap.skipToken = SKIP_TOKEN; + navInfo.progressIndicator = true; + navInfo.tuneId = TUNE_TAP_CASUAL; + + displayReviewPage(0, false); } /** - * @brief Draws a flow of pages of a review. A back key is available on top-left of the screen, except in first page - * It is possible to go to next page thanks to "tap to continue". - * @note All tag/value pairs are provided in the API and the number of pages is automatically computed, the last page - * being a long press one + * @brief Draws a flow of pages of a review. A back key is available on top-left of the screen, + * except in first page It is possible to go to next page thanks to "tap to continue". + * @note All tag/value pairs are provided in the API and the number of pages is automatically + * computed, the last page being a long press one * * @param tagValueList list of tag/value pairs * @param infoLongPress information to build the last page * @param rejectText text to use in footer - * @param callback callback called when transaction is accepted (param is true) or rejected (param is false) + * @param callback callback called when transaction is accepted (param is true) or rejected (param + * is false) */ void nbgl_useCaseStaticReview(const nbgl_layoutTagValueList_t *tagValueList, - const nbgl_pageInfoLongPress_t *infoLongPress, - const char *rejectText, - nbgl_choiceCallback_t callback) { - // memorize context - onChoice = callback; - onNav = NULL; - forwardNavOnly = false; - - staticReviewContext.withLongPress = true; - memcpy(&staticReviewContext.tagValueList, tagValueList, sizeof(nbgl_layoutTagValueList_t)); - memcpy(&staticReviewContext.infoLongPress, infoLongPress, sizeof(nbgl_pageInfoLongPress_t)); - staticReviewContext.currentPairIndex = 0; - staticReviewContext.nbPairsInCurrentPage = 0; - - // compute number of pages & fill navigation structure - navInfo.nbPages = nbgl_useCaseGetNbPagesForTagValueList(tagValueList) + 1; - navInfo.activePage = 0; - navInfo.navType = NAV_WITH_TAP; - navInfo.quitToken = REJECT_TOKEN; - navInfo.navWithTap.nextPageToken = NEXT_TOKEN; - navInfo.navWithTap.quitText = rejectText; - navInfo.navWithTap.backToken = BACK_TOKEN; - navInfo.navWithTap.skipText = NULL; - navInfo.progressIndicator = true; - navInfo.tuneId = TUNE_TAP_CASUAL; - - displayStaticReviewPage(0, true); + const nbgl_pageInfoLongPress_t *infoLongPress, + const char *rejectText, + nbgl_choiceCallback_t callback) +{ + // memorize context + onChoice = callback; + onNav = NULL; + forwardNavOnly = false; + + staticReviewContext.withLongPress = true; + memcpy(&staticReviewContext.tagValueList, tagValueList, sizeof(nbgl_layoutTagValueList_t)); + memcpy(&staticReviewContext.infoLongPress, infoLongPress, sizeof(nbgl_pageInfoLongPress_t)); + staticReviewContext.currentPairIndex = 0; + staticReviewContext.nbPairsInCurrentPage = 0; + + // compute number of pages & fill navigation structure + navInfo.nbPages = nbgl_useCaseGetNbPagesForTagValueList(tagValueList) + 1; + navInfo.activePage = 0; + navInfo.navType = NAV_WITH_TAP; + navInfo.quitToken = REJECT_TOKEN; + navInfo.navWithTap.nextPageToken = NEXT_TOKEN; + navInfo.navWithTap.quitText = rejectText; + navInfo.navWithTap.backToken = BACK_TOKEN; + navInfo.navWithTap.skipText = NULL; + navInfo.progressIndicator = true; + navInfo.tuneId = TUNE_TAP_CASUAL; + + displayStaticReviewPage(0, true); } /** - * @brief Similar to @ref nbgl_useCaseStaticReview() but with a simple button/footer pair instead of a long press button/footer pair. - * @note All tag/value pairs are provided in the API and the number of pages is automatically computed, the last page - * being a long press one + * @brief Similar to @ref nbgl_useCaseStaticReview() but with a simple button/footer pair instead of + * a long press button/footer pair. + * @note All tag/value pairs are provided in the API and the number of pages is automatically + * computed, the last page being a long press one * * @param tagValueList list of tag/value pairs - * @param infoLongPress information to build the last page (even if not a real long press, the info is the same) + * @param infoLongPress information to build the last page (even if not a real long press, the info + * is the same) * @param rejectText text to use in footer - * @param callback callback called when transaction is accepted (param is true) or rejected (param is false) + * @param callback callback called when transaction is accepted (param is true) or rejected (param + * is false) */ void nbgl_useCaseStaticReviewLight(const nbgl_layoutTagValueList_t *tagValueList, - const nbgl_pageInfoLongPress_t *infoLongPress, - const char *rejectText, - nbgl_choiceCallback_t callback) { - // memorize context - onChoice = callback; - onNav = NULL; - forwardNavOnly = false; - - staticReviewContext.withLongPress = false; - memcpy(&staticReviewContext.tagValueList,tagValueList,sizeof(nbgl_layoutTagValueList_t)); - memcpy(&staticReviewContext.infoLongPress,infoLongPress,sizeof(nbgl_pageInfoLongPress_t)); - staticReviewContext.currentPairIndex = 0; - staticReviewContext.nbPairsInCurrentPage = 0; - - // compute number of pages & fill navigation structure - navInfo.nbPages = nbgl_useCaseGetNbPagesForTagValueList(tagValueList)+1; - navInfo.activePage = 0; - navInfo.navType = NAV_WITH_TAP; - navInfo.quitToken = REJECT_TOKEN; - navInfo.navWithTap.nextPageToken = NEXT_TOKEN; - navInfo.navWithTap.quitText = rejectText; - navInfo.navWithTap.backToken = BACK_TOKEN; - navInfo.navWithTap.skipText = NULL; - navInfo.progressIndicator = true; - navInfo.tuneId = TUNE_TAP_CASUAL; - - displayStaticReviewPage(0, true); + const nbgl_pageInfoLongPress_t *infoLongPress, + const char *rejectText, + nbgl_choiceCallback_t callback) +{ + // memorize context + onChoice = callback; + onNav = NULL; + forwardNavOnly = false; + + staticReviewContext.withLongPress = false; + memcpy(&staticReviewContext.tagValueList, tagValueList, sizeof(nbgl_layoutTagValueList_t)); + memcpy(&staticReviewContext.infoLongPress, infoLongPress, sizeof(nbgl_pageInfoLongPress_t)); + staticReviewContext.currentPairIndex = 0; + staticReviewContext.nbPairsInCurrentPage = 0; + + // compute number of pages & fill navigation structure + navInfo.nbPages = nbgl_useCaseGetNbPagesForTagValueList(tagValueList) + 1; + navInfo.activePage = 0; + navInfo.navType = NAV_WITH_TAP; + navInfo.quitToken = REJECT_TOKEN; + navInfo.navWithTap.nextPageToken = NEXT_TOKEN; + navInfo.navWithTap.quitText = rejectText; + navInfo.navWithTap.backToken = BACK_TOKEN; + navInfo.navWithTap.skipText = NULL; + navInfo.progressIndicator = true; + navInfo.tuneId = TUNE_TAP_CASUAL; + + displayStaticReviewPage(0, true); } /** - * @brief Draws a flow of pages to view details on a given tag/value pair that doesn't fit in a single page + * @brief Draws a flow of pages to view details on a given tag/value pair that doesn't fit in a + * single page * * @param tag tag name (in gray) * @param value full value string, that will be split in multiple pages * @param wrapping if set to true, value text is wrapped on ' ' characters */ -void nbgl_useCaseViewDetails(const char *tag, const char *value, bool wrapping) { - uint16_t nbLines = nbgl_getTextNbLinesInWidth(BAGL_FONT_INTER_REGULAR_24px, value, SCREEN_WIDTH-2*BORDER_MARGIN, wrapping); - - // initialize context - detailsContext.tag = tag; - detailsContext.value = value; - detailsContext.nbPages = (nbLines+NB_MAX_LINES_IN_DETAILS-1)/NB_MAX_LINES_IN_DETAILS; - detailsContext.currentPage = 0; - detailsContext.wrapping = wrapping; - // add some spare for room lost with "..." substitution - if (detailsContext.nbPages > 1) { - uint16_t nbLostChars = (detailsContext.nbPages - 1)*3; - uint16_t nbLostLines = (nbLostChars+((SCREEN_WIDTH-2*BORDER_MARGIN)/16)-1)/((SCREEN_WIDTH-2*BORDER_MARGIN)/16); // 16 for average char width - uint8_t nbLinesInLastPage = nbLines - ((detailsContext.nbPages - 1)*NB_MAX_LINES_IN_DETAILS); - - detailsContext.nbPages += nbLostLines/NB_MAX_LINES_IN_DETAILS; - if ((nbLinesInLastPage + (nbLostLines%NB_MAX_LINES_IN_DETAILS))>NB_MAX_LINES_IN_DETAILS) { - detailsContext.nbPages ++; - } - } - - displayDetailsPage(0, true); +void nbgl_useCaseViewDetails(const char *tag, const char *value, bool wrapping) +{ + uint16_t nbLines = nbgl_getTextNbLinesInWidth( + BAGL_FONT_INTER_REGULAR_24px, value, SCREEN_WIDTH - 2 * BORDER_MARGIN, wrapping); + + // initialize context + detailsContext.tag = tag; + detailsContext.value = value; + detailsContext.nbPages = (nbLines + NB_MAX_LINES_IN_DETAILS - 1) / NB_MAX_LINES_IN_DETAILS; + detailsContext.currentPage = 0; + detailsContext.wrapping = wrapping; + // add some spare for room lost with "..." substitution + if (detailsContext.nbPages > 1) { + uint16_t nbLostChars = (detailsContext.nbPages - 1) * 3; + uint16_t nbLostLines + = (nbLostChars + ((SCREEN_WIDTH - 2 * BORDER_MARGIN) / 16) - 1) + / ((SCREEN_WIDTH - 2 * BORDER_MARGIN) / 16); // 16 for average char width + uint8_t nbLinesInLastPage + = nbLines - ((detailsContext.nbPages - 1) * NB_MAX_LINES_IN_DETAILS); + + detailsContext.nbPages += nbLostLines / NB_MAX_LINES_IN_DETAILS; + if ((nbLinesInLastPage + (nbLostLines % NB_MAX_LINES_IN_DETAILS)) + > NB_MAX_LINES_IN_DETAILS) { + detailsContext.nbPages++; + } + } + + displayDetailsPage(0, true); } /** - * @brief draws an address confirmation page. This page contains the given address in a tag/value layout, with a button to - * open a modal to see address as a QR Code, - * and at the bottom a button to confirm and a footer to cancel + * @brief draws an address confirmation page. This page contains the given address in a tag/value + * layout, with a button to open a modal to see address as a QR Code, and at the bottom a button to + * confirm and a footer to cancel * * @param address address to confirm (NULL terminated string) - * @param callback callback called when button or footer is touched (if true, button, if false footer) - */ -void nbgl_useCaseAddressConfirmation(const char *address, nbgl_choiceCallback_t callback) { - nbgl_useCaseAddressConfirmationExt(address, callback, NULL); + * @param callback callback called when button or footer is touched (if true, button, if false + * footer) + */ +void nbgl_useCaseAddressConfirmation(const char *address, nbgl_choiceCallback_t callback) +{ + nbgl_useCaseAddressConfirmationExt(address, callback, NULL); } /** - * @brief draws an extended address verification page. This page contains the given address in a tag/value layout, with a button to - * open a modal to see address as a QR Code. - * A "tap to continue" enables to open a second review page to display the other given tag/value pairs, with a button to confirm and a footer to cancel + * @brief draws an extended address verification page. This page contains the given address in a + * tag/value layout, with a button to open a modal to see address as a QR Code. A "tap to continue" + * enables to open a second review page to display the other given tag/value pairs, with a button to + * confirm and a footer to cancel * * @param address address to confirm (NULL terminated string) - * @param callback callback called when button or footer is touched (if true, button, if false footer) - * @param tagValueList list of tag/value pairs (must fit in a single page, and be persistent because no copy) - */ -void nbgl_useCaseAddressConfirmationExt(const char *address, nbgl_choiceCallback_t callback, const nbgl_layoutTagValueList_t *tagValueList) { - // save context - onChoice = callback; - addressConfirmationContext.address = address; - addressConfirmationContext.tagValueList = tagValueList; - - // fill navigation structure, common to all pages - navInfo.navType = NAV_WITH_TAP; - navInfo.nbPages = (tagValueList == NULL)? 0 : 2; - navInfo.progressIndicator = true; - navInfo.tuneId = TUNE_TAP_CASUAL; - navInfo.navWithTap.backButton = (tagValueList != NULL); - navInfo.navWithTap.quitText = "Cancel"; - navInfo.navWithTap.nextPageToken = ADDR_NEXT_TOKEN; - navInfo.navWithTap.backToken = ADDR_BACK_TOKEN; - navInfo.navWithTap.skipText = NULL; - navInfo.quitToken = REJECT_TOKEN; - - displayAddressPage(0, true); + * @param callback callback called when button or footer is touched (if true, button, if false + * footer) + * @param tagValueList list of tag/value pairs (must fit in a single page, and be persistent because + * no copy) + */ +void nbgl_useCaseAddressConfirmationExt(const char *address, + nbgl_choiceCallback_t callback, + const nbgl_layoutTagValueList_t *tagValueList) +{ + // save context + onChoice = callback; + addressConfirmationContext.address = address; + addressConfirmationContext.tagValueList = tagValueList; + + // fill navigation structure, common to all pages + navInfo.navType = NAV_WITH_TAP; + navInfo.nbPages = (tagValueList == NULL) ? 0 : 2; + navInfo.progressIndicator = true; + navInfo.tuneId = TUNE_TAP_CASUAL; + navInfo.navWithTap.backButton = (tagValueList != NULL); + navInfo.navWithTap.quitText = "Cancel"; + navInfo.navWithTap.nextPageToken = ADDR_NEXT_TOKEN; + navInfo.navWithTap.backToken = ADDR_BACK_TOKEN; + navInfo.navWithTap.skipText = NULL; + navInfo.quitToken = REJECT_TOKEN; + + displayAddressPage(0, true); } /** - * @brief draw a spinner page with the given parameters. The spinner will "turn" automatically every 800 ms + * @brief draw a spinner page with the given parameters. The spinner will "turn" automatically every + * 800 ms * * @param text text to use under spinner */ -void nbgl_useCaseSpinner(const char *text) { - pageContext = nbgl_pageDrawSpinner(NULL, (const char*)text); - nbgl_refreshSpecial(FULL_COLOR_PARTIAL_REFRESH); +void nbgl_useCaseSpinner(const char *text) +{ + pageContext = nbgl_pageDrawSpinner(NULL, (const char *) text); + nbgl_refreshSpecial(FULL_COLOR_PARTIAL_REFRESH); } -#endif // NBGL_USE_CASE +#endif // NBGL_USE_CASE diff --git a/lib_nfc/include/nfc_ndef.h b/lib_nfc/include/nfc_ndef.h index c0e250b5c..b3c176a84 100644 --- a/lib_nfc/include/nfc_ndef.h +++ b/lib_nfc/include/nfc_ndef.h @@ -8,90 +8,89 @@ * DEFINES *********************/ // From ST lib_NDEF.h -#define URI_ID_0x00 0x00 -#define URI_ID_0x01 0x01 -#define URI_ID_0x02 0x02 -#define URI_ID_0x03 0x03 -#define URI_ID_0x04 0x04 -#define URI_ID_0x05 0x05 -#define URI_ID_0x06 0x06 -#define URI_ID_0x07 0x07 -#define URI_ID_0x08 0x08 -#define URI_ID_0x09 0x09 -#define URI_ID_0x0A 0x0A -#define URI_ID_0x0B 0x0B -#define URI_ID_0x0C 0x0C -#define URI_ID_0x0D 0x0D -#define URI_ID_0x0E 0x0E -#define URI_ID_0x0F 0x0F -#define URI_ID_0x10 0x10 -#define URI_ID_0x11 0x11 -#define URI_ID_0x12 0x12 -#define URI_ID_0x13 0x13 -#define URI_ID_0x14 0x14 -#define URI_ID_0x15 0x15 -#define URI_ID_0x16 0x16 -#define URI_ID_0x17 0x17 -#define URI_ID_0x18 0x18 -#define URI_ID_0x19 0x19 -#define URI_ID_0x1A 0x1A -#define URI_ID_0x1B 0x1B -#define URI_ID_0x1C 0x1C -#define URI_ID_0x1D 0x1D -#define URI_ID_0x1E 0x1E -#define URI_ID_0x1F 0x1F -#define URI_ID_0x20 0x20 -#define URI_ID_0x21 0x21 -#define URI_ID_0x22 0x22 -#define URI_ID_0x23 0x23 -#define URI_RFU 0x24 +#define URI_ID_0x00 0x00 +#define URI_ID_0x01 0x01 +#define URI_ID_0x02 0x02 +#define URI_ID_0x03 0x03 +#define URI_ID_0x04 0x04 +#define URI_ID_0x05 0x05 +#define URI_ID_0x06 0x06 +#define URI_ID_0x07 0x07 +#define URI_ID_0x08 0x08 +#define URI_ID_0x09 0x09 +#define URI_ID_0x0A 0x0A +#define URI_ID_0x0B 0x0B +#define URI_ID_0x0C 0x0C +#define URI_ID_0x0D 0x0D +#define URI_ID_0x0E 0x0E +#define URI_ID_0x0F 0x0F +#define URI_ID_0x10 0x10 +#define URI_ID_0x11 0x11 +#define URI_ID_0x12 0x12 +#define URI_ID_0x13 0x13 +#define URI_ID_0x14 0x14 +#define URI_ID_0x15 0x15 +#define URI_ID_0x16 0x16 +#define URI_ID_0x17 0x17 +#define URI_ID_0x18 0x18 +#define URI_ID_0x19 0x19 +#define URI_ID_0x1A 0x1A +#define URI_ID_0x1B 0x1B +#define URI_ID_0x1C 0x1C +#define URI_ID_0x1D 0x1D +#define URI_ID_0x1E 0x1E +#define URI_ID_0x1F 0x1F +#define URI_ID_0x20 0x20 +#define URI_ID_0x21 0x21 +#define URI_ID_0x22 0x22 +#define URI_ID_0x23 0x23 +#define URI_RFU 0x24 -#define URI_ID_0x01_STRING "http://www.\0" -#define URI_ID_0x02_STRING "https://www.\0" -#define URI_ID_0x03_STRING "http://\0" -#define URI_ID_0x04_STRING "https://\0" -#define URI_ID_0x05_STRING "tel:\0" -#define URI_ID_0x06_STRING "mailto:\0" -#define URI_ID_0x07_STRING "ftp://anonymous:anonymous@\0" -#define URI_ID_0x08_STRING "ftp://ftp.\0" -#define URI_ID_0x09_STRING "ftps://\0" -#define URI_ID_0x0A_STRING "sftp://\0" -#define URI_ID_0x0B_STRING "smb://\0" -#define URI_ID_0x0C_STRING "nfs://\0" -#define URI_ID_0x0D_STRING "ftp://\0" -#define URI_ID_0x0E_STRING "dav://\0" -#define URI_ID_0x0F_STRING "news:\0" -#define URI_ID_0x10_STRING "telnet://\0" -#define URI_ID_0x11_STRING "imap:\0" -#define URI_ID_0x12_STRING "rtsp://\0" -#define URI_ID_0x13_STRING "urn:\0" -#define URI_ID_0x14_STRING "pop:\0" -#define URI_ID_0x15_STRING "sip:\0" -#define URI_ID_0x16_STRING "sips:\0" -#define URI_ID_0x17_STRING "tftp:\0" -#define URI_ID_0x18_STRING "btspp://\0" -#define URI_ID_0x19_STRING "btl2cap://\0" -#define URI_ID_0x1A_STRING "btgoep://\0" -#define URI_ID_0x1B_STRING "tcpobex://\0" -#define URI_ID_0x1C_STRING "irdaobex://\0" -#define URI_ID_0x1D_STRING "file://\0" -#define URI_ID_0x1E_STRING "urn:epc:id:\0" -#define URI_ID_0x1F_STRING "urn:epc:tag\0" -#define URI_ID_0x20_STRING "urn:epc:pat:\0" -#define URI_ID_0x21_STRING "urn:epc:raw:\0" -#define URI_ID_0x22_STRING "urn:epc:\0" -#define URI_ID_0x23_STRING "urn:nfc:\0" +#define URI_ID_0x01_STRING "http://www.\0" +#define URI_ID_0x02_STRING "https://www.\0" +#define URI_ID_0x03_STRING "http://\0" +#define URI_ID_0x04_STRING "https://\0" +#define URI_ID_0x05_STRING "tel:\0" +#define URI_ID_0x06_STRING "mailto:\0" +#define URI_ID_0x07_STRING "ftp://anonymous:anonymous@\0" +#define URI_ID_0x08_STRING "ftp://ftp.\0" +#define URI_ID_0x09_STRING "ftps://\0" +#define URI_ID_0x0A_STRING "sftp://\0" +#define URI_ID_0x0B_STRING "smb://\0" +#define URI_ID_0x0C_STRING "nfs://\0" +#define URI_ID_0x0D_STRING "ftp://\0" +#define URI_ID_0x0E_STRING "dav://\0" +#define URI_ID_0x0F_STRING "news:\0" +#define URI_ID_0x10_STRING "telnet://\0" +#define URI_ID_0x11_STRING "imap:\0" +#define URI_ID_0x12_STRING "rtsp://\0" +#define URI_ID_0x13_STRING "urn:\0" +#define URI_ID_0x14_STRING "pop:\0" +#define URI_ID_0x15_STRING "sip:\0" +#define URI_ID_0x16_STRING "sips:\0" +#define URI_ID_0x17_STRING "tftp:\0" +#define URI_ID_0x18_STRING "btspp://\0" +#define URI_ID_0x19_STRING "btl2cap://\0" +#define URI_ID_0x1A_STRING "btgoep://\0" +#define URI_ID_0x1B_STRING "tcpobex://\0" +#define URI_ID_0x1C_STRING "irdaobex://\0" +#define URI_ID_0x1D_STRING "file://\0" +#define URI_ID_0x1E_STRING "urn:epc:id:\0" +#define URI_ID_0x1F_STRING "urn:epc:tag\0" +#define URI_ID_0x20_STRING "urn:epc:pat:\0" +#define URI_ID_0x21_STRING "urn:epc:raw:\0" +#define URI_ID_0x22_STRING "urn:epc:\0" +#define URI_ID_0x23_STRING "urn:nfc:\0" -#define URI_ID_STRING_MAX_LEN 27 //strlen(URI_ID_0x07_STRING)+1 +#define URI_ID_STRING_MAX_LEN 27 // strlen(URI_ID_0x07_STRING)+1 -#define NFC_TEXT_MAX_LEN 215 -#define NFC_INFO_MAX_LEN 30 +#define NFC_TEXT_MAX_LEN 215 +#define NFC_INFO_MAX_LEN 30 -#define NFC_NDEF_MAX_SIZE (URI_ID_STRING_MAX_LEN+NFC_TEXT_MAX_LEN+NFC_INFO_MAX_LEN+1) - -#define NFC_NDEF_TYPE_TEXT 0x01 -#define NFC_NDEF_TYPE_URI 0x02 +#define NFC_NDEF_MAX_SIZE (URI_ID_STRING_MAX_LEN + NFC_TEXT_MAX_LEN + NFC_INFO_MAX_LEN + 1) +#define NFC_NDEF_TYPE_TEXT 0x01 +#define NFC_NDEF_TYPE_URI 0x02 /********************** * TYPEDEFS @@ -101,18 +100,17 @@ * @brief Structure to store an NDEF message */ typedef struct __attribute__((packed)) ndef_struct_s { - uint8_t ndef_type; // NDEF message type NFC_NDEF_TYPE_TEXT / NFC_NDEF_TYPE_URI - uint8_t uri_id; // URI string id (only applicable for NFC_NDEF_TYPE_URI) - char text[NFC_TEXT_MAX_LEN+1]; // String to store NDEF text/uri +1 for \0 - char info[NFC_INFO_MAX_LEN+1]; // String to store NDEF uri information +1 for \0 + uint8_t ndef_type; // NDEF message type NFC_NDEF_TYPE_TEXT / NFC_NDEF_TYPE_URI + uint8_t uri_id; // URI string id (only applicable for NFC_NDEF_TYPE_URI) + char text[NFC_TEXT_MAX_LEN + 1]; // String to store NDEF text/uri +1 for \0 + char info[NFC_INFO_MAX_LEN + 1]; // String to store NDEF uri information +1 for \0 } ndef_struct_t; - /********************** * GLOBAL PROTOTYPES **********************/ uint16_t os_get_uri_header(uint8_t uri_id, char *uri_header); -uint8_t os_parse_ndef(uint8_t *in_buffer, ndef_struct_t *parsed); -uint16_t os_ndef_to_string(ndef_struct_t *ndef_message, char * out_string); +uint8_t os_parse_ndef(uint8_t *in_buffer, ndef_struct_t *parsed); +uint16_t os_ndef_to_string(ndef_struct_t *ndef_message, char *out_string); #endif diff --git a/lib_nfc/src/nfc_ndef.c b/lib_nfc/src/nfc_ndef.c index 16579b5d6..6e3eca6a7 100644 --- a/lib_nfc/src/nfc_ndef.c +++ b/lib_nfc/src/nfc_ndef.c @@ -4,7 +4,6 @@ #include "string.h" #include "os_apdu.h" - /********************** * GLOBAL FUNCTIONS **********************/ @@ -16,118 +15,119 @@ * @param uri_header URI header string * @return URI header string length */ -uint16_t os_get_uri_header(uint8_t uri_id, char *uri_header) { - switch (uri_id) { - case URI_ID_0x01: - strcpy(uri_header, URI_ID_0x01_STRING); - break; - case URI_ID_0x02: - strcpy(uri_header, URI_ID_0x02_STRING); - break; - case URI_ID_0x03: - strcpy(uri_header, URI_ID_0x03_STRING); - break; - case URI_ID_0x04: - strcpy(uri_header, URI_ID_0x04_STRING); - break; - case URI_ID_0x05: - strcpy(uri_header, URI_ID_0x05_STRING); - break; - case URI_ID_0x06: - strcpy(uri_header, URI_ID_0x06_STRING); - break; - case URI_ID_0x07: - strcpy(uri_header, URI_ID_0x07_STRING); - break; - case URI_ID_0x08: - strcpy(uri_header, URI_ID_0x08_STRING); - break; - case URI_ID_0x09: - strcpy(uri_header, URI_ID_0x09_STRING); - break; - case URI_ID_0x0A: - strcpy(uri_header, URI_ID_0x0A_STRING); - break; - case URI_ID_0x0B: - strcpy(uri_header, URI_ID_0x0B_STRING); - break; - case URI_ID_0x0C: - strcpy(uri_header, URI_ID_0x0C_STRING); - break; - case URI_ID_0x0D: - strcpy(uri_header, URI_ID_0x0D_STRING); - break; - case URI_ID_0x0E: - strcpy(uri_header, URI_ID_0x0E_STRING); - break; - case URI_ID_0x0F: - strcpy(uri_header, URI_ID_0x0F_STRING); - break; - case URI_ID_0x10: - strcpy(uri_header, URI_ID_0x10_STRING); - break; - case URI_ID_0x11: - strcpy(uri_header, URI_ID_0x11_STRING); - break; - case URI_ID_0x12: - strcpy(uri_header, URI_ID_0x12_STRING); - break; - case URI_ID_0x13: - strcpy(uri_header, URI_ID_0x13_STRING); - break; - case URI_ID_0x14: - strcpy(uri_header, URI_ID_0x14_STRING); - break; - case URI_ID_0x15: - strcpy(uri_header, URI_ID_0x15_STRING); - break; - case URI_ID_0x16: - strcpy(uri_header, URI_ID_0x16_STRING); - break; - case URI_ID_0x17: - strcpy(uri_header, URI_ID_0x17_STRING); - break; - case URI_ID_0x18: - strcpy(uri_header, URI_ID_0x18_STRING); - break; - case URI_ID_0x19: - strcpy(uri_header, URI_ID_0x19_STRING); - break; - case URI_ID_0x1A: - strcpy(uri_header, URI_ID_0x1A_STRING); - break; - case URI_ID_0x1B: - strcpy(uri_header, URI_ID_0x1B_STRING); - break; - case URI_ID_0x1C: - strcpy(uri_header, URI_ID_0x1C_STRING); - break; - case URI_ID_0x1D: - strcpy(uri_header, URI_ID_0x1D_STRING); - break; - case URI_ID_0x1E: - strcpy(uri_header, URI_ID_0x1E_STRING); - break; - case URI_ID_0x1F: - strcpy(uri_header, URI_ID_0x1F_STRING); - break; - case URI_ID_0x20: - strcpy(uri_header, URI_ID_0x20_STRING); - break; - case URI_ID_0x21: - strcpy(uri_header, URI_ID_0x21_STRING); - break; - case URI_ID_0x22: - strcpy(uri_header, URI_ID_0x22_STRING); - break; - case URI_ID_0x23: - strcpy(uri_header, URI_ID_0x23_STRING); - break; - default: - return 0; - break; - } - return strlen(uri_header); +uint16_t os_get_uri_header(uint8_t uri_id, char *uri_header) +{ + switch (uri_id) { + case URI_ID_0x01: + strcpy(uri_header, URI_ID_0x01_STRING); + break; + case URI_ID_0x02: + strcpy(uri_header, URI_ID_0x02_STRING); + break; + case URI_ID_0x03: + strcpy(uri_header, URI_ID_0x03_STRING); + break; + case URI_ID_0x04: + strcpy(uri_header, URI_ID_0x04_STRING); + break; + case URI_ID_0x05: + strcpy(uri_header, URI_ID_0x05_STRING); + break; + case URI_ID_0x06: + strcpy(uri_header, URI_ID_0x06_STRING); + break; + case URI_ID_0x07: + strcpy(uri_header, URI_ID_0x07_STRING); + break; + case URI_ID_0x08: + strcpy(uri_header, URI_ID_0x08_STRING); + break; + case URI_ID_0x09: + strcpy(uri_header, URI_ID_0x09_STRING); + break; + case URI_ID_0x0A: + strcpy(uri_header, URI_ID_0x0A_STRING); + break; + case URI_ID_0x0B: + strcpy(uri_header, URI_ID_0x0B_STRING); + break; + case URI_ID_0x0C: + strcpy(uri_header, URI_ID_0x0C_STRING); + break; + case URI_ID_0x0D: + strcpy(uri_header, URI_ID_0x0D_STRING); + break; + case URI_ID_0x0E: + strcpy(uri_header, URI_ID_0x0E_STRING); + break; + case URI_ID_0x0F: + strcpy(uri_header, URI_ID_0x0F_STRING); + break; + case URI_ID_0x10: + strcpy(uri_header, URI_ID_0x10_STRING); + break; + case URI_ID_0x11: + strcpy(uri_header, URI_ID_0x11_STRING); + break; + case URI_ID_0x12: + strcpy(uri_header, URI_ID_0x12_STRING); + break; + case URI_ID_0x13: + strcpy(uri_header, URI_ID_0x13_STRING); + break; + case URI_ID_0x14: + strcpy(uri_header, URI_ID_0x14_STRING); + break; + case URI_ID_0x15: + strcpy(uri_header, URI_ID_0x15_STRING); + break; + case URI_ID_0x16: + strcpy(uri_header, URI_ID_0x16_STRING); + break; + case URI_ID_0x17: + strcpy(uri_header, URI_ID_0x17_STRING); + break; + case URI_ID_0x18: + strcpy(uri_header, URI_ID_0x18_STRING); + break; + case URI_ID_0x19: + strcpy(uri_header, URI_ID_0x19_STRING); + break; + case URI_ID_0x1A: + strcpy(uri_header, URI_ID_0x1A_STRING); + break; + case URI_ID_0x1B: + strcpy(uri_header, URI_ID_0x1B_STRING); + break; + case URI_ID_0x1C: + strcpy(uri_header, URI_ID_0x1C_STRING); + break; + case URI_ID_0x1D: + strcpy(uri_header, URI_ID_0x1D_STRING); + break; + case URI_ID_0x1E: + strcpy(uri_header, URI_ID_0x1E_STRING); + break; + case URI_ID_0x1F: + strcpy(uri_header, URI_ID_0x1F_STRING); + break; + case URI_ID_0x20: + strcpy(uri_header, URI_ID_0x20_STRING); + break; + case URI_ID_0x21: + strcpy(uri_header, URI_ID_0x21_STRING); + break; + case URI_ID_0x22: + strcpy(uri_header, URI_ID_0x22_STRING); + break; + case URI_ID_0x23: + strcpy(uri_header, URI_ID_0x23_STRING); + break; + default: + return 0; + break; + } + return strlen(uri_header); } /** @@ -137,22 +137,23 @@ uint16_t os_get_uri_header(uint8_t uri_id, char *uri_header) { * @param parsed deserialized output * @return bolos error */ -uint8_t os_parse_ndef(uint8_t *in_buffer, ndef_struct_t *parsed) { +uint8_t os_parse_ndef(uint8_t *in_buffer, ndef_struct_t *parsed) +{ uint8_t text_length, info_length; parsed->ndef_type = in_buffer[APDU_OFF_P1]; - parsed->uri_id = in_buffer[APDU_OFF_P2]; - text_length = in_buffer[APDU_OFF_DATA]; + parsed->uri_id = in_buffer[APDU_OFF_P2]; + text_length = in_buffer[APDU_OFF_DATA]; if (text_length > NFC_TEXT_MAX_LEN) { return 1; } - memcpy(parsed->text, &in_buffer[APDU_OFF_DATA+1], text_length); + memcpy(parsed->text, &in_buffer[APDU_OFF_DATA + 1], text_length); parsed->text[text_length] = '\0'; - info_length = in_buffer[APDU_OFF_DATA+1+text_length]; + info_length = in_buffer[APDU_OFF_DATA + 1 + text_length]; if (info_length > NFC_INFO_MAX_LEN) { return 1; } if (info_length) { - memcpy(parsed->info, &in_buffer[APDU_OFF_DATA+1+text_length+1], info_length); + memcpy(parsed->info, &in_buffer[APDU_OFF_DATA + 1 + text_length + 1], info_length); parsed->info[info_length] = '\0'; } return 0; @@ -165,13 +166,14 @@ uint8_t os_parse_ndef(uint8_t *in_buffer, ndef_struct_t *parsed) { * @param out_string output string * @return output string length */ -uint16_t os_ndef_to_string(ndef_struct_t *ndef_message, char * out_string) { - uint16_t tot_length = 0; +uint16_t os_ndef_to_string(ndef_struct_t *ndef_message, char *out_string) +{ + uint16_t tot_length = 0; uint16_t length_internal = 0; if (ndef_message->ndef_type == NFC_NDEF_TYPE_TEXT) { tot_length += strlen(ndef_message->text); if (tot_length > NFC_TEXT_MAX_LEN) { - return 0; + return 0; } strcpy(out_string, ndef_message->text); } @@ -179,15 +181,15 @@ uint16_t os_ndef_to_string(ndef_struct_t *ndef_message, char * out_string) { tot_length += os_get_uri_header(ndef_message->uri_id, out_string); length_internal = strlen(ndef_message->text); if (tot_length + length_internal > URI_ID_STRING_MAX_LEN + NFC_TEXT_MAX_LEN) { - return 0; + return 0; } strcpy(&out_string[tot_length], ndef_message->text); tot_length += length_internal; if (ndef_message->info[0] != '\0') { out_string[tot_length++] = '\n'; - length_internal = strlen(ndef_message->info); + length_internal = strlen(ndef_message->info); if (tot_length + length_internal > NFC_NDEF_MAX_SIZE) { - return 0; + return 0; } strcpy(&out_string[tot_length], ndef_message->info); tot_length += length_internal; @@ -195,5 +197,5 @@ uint16_t os_ndef_to_string(ndef_struct_t *ndef_message, char * out_string) { } return tot_length; } -#endif // HAVE_NDEF_SUPPORT -#endif // HAVE_NFC +#endif // HAVE_NDEF_SUPPORT +#endif // HAVE_NFC diff --git a/lib_standard_app/base58.c b/lib_standard_app/base58.c index 4c15dbd67..9c4bf5011 100644 --- a/lib_standard_app/base58.c +++ b/lib_standard_app/base58.c @@ -42,8 +42,9 @@ char const BASE58_ALPHABET[] = { 'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z' // }; -int base58_decode(const char *in, size_t in_len, uint8_t *out, size_t out_len) { - uint8_t tmp[MAX_DEC_INPUT_SIZE] = {0}; +int base58_decode(const char *in, size_t in_len, uint8_t *out, size_t out_len) +{ + uint8_t tmp[MAX_DEC_INPUT_SIZE] = {0}; uint8_t buffer[MAX_DEC_INPUT_SIZE] = {0}; uint8_t j; uint8_t start_at; @@ -71,15 +72,15 @@ int base58_decode(const char *in, size_t in_len, uint8_t *out, size_t out_len) { ++zero_count; } - j = in_len; + j = in_len; start_at = zero_count; while (start_at < in_len) { uint16_t remainder = 0; for (uint8_t div_loop = start_at; div_loop < in_len; div_loop++) { - uint16_t digit256 = (uint16_t)(tmp[div_loop] & 0xFF); - uint16_t tmp_div = remainder * 58 + digit256; - tmp[div_loop] = (uint8_t)(tmp_div / 256); - remainder = tmp_div % 256; + uint16_t digit256 = (uint16_t) (tmp[div_loop] & 0xFF); + uint16_t tmp_div = remainder * 58 + digit256; + tmp[div_loop] = (uint8_t) (tmp_div / 256); + remainder = tmp_div % 256; } if (tmp[start_at] == 0) { @@ -104,12 +105,13 @@ int base58_decode(const char *in, size_t in_len, uint8_t *out, size_t out_len) { return length; } -int base58_encode(const uint8_t *in, size_t in_len, char *out, size_t out_len) { +int base58_encode(const uint8_t *in, size_t in_len, char *out, size_t out_len) +{ uint8_t buffer[MAX_ENC_INPUT_SIZE * 138 / 100 + 1] = {0}; - size_t i, j; - size_t stop_at; - size_t zero_count = 0; - size_t output_size; + size_t i, j; + size_t stop_at; + size_t zero_count = 0; + size_t output_size; if (in_len > MAX_ENC_INPUT_SIZE) { return -1; @@ -120,7 +122,7 @@ int base58_encode(const uint8_t *in, size_t in_len, char *out, size_t out_len) { } output_size = (in_len - zero_count) * 138 / 100 + 1; - stop_at = output_size - 1; + stop_at = output_size - 1; for (size_t start_at = zero_count; start_at < in_len; start_at++) { int carry = in[start_at]; for (j = output_size - 1; (int) j >= 0; j--) { diff --git a/lib_standard_app/bip32.c b/lib_standard_app/bip32.c index a6ac6e59b..cc7003087 100644 --- a/lib_standard_app/bip32.c +++ b/lib_standard_app/bip32.c @@ -23,7 +23,8 @@ #include "bip32.h" #include "read.h" -bool bip32_path_read(const uint8_t *in, size_t in_len, uint32_t *out, size_t out_len) { +bool bip32_path_read(const uint8_t *in, size_t in_len, uint32_t *out, size_t out_len) +{ if (out_len == 0 || out_len > MAX_BIP32_PATH) { return false; } @@ -41,10 +42,8 @@ bool bip32_path_read(const uint8_t *in, size_t in_len, uint32_t *out, size_t out return true; } -bool bip32_path_format(const uint32_t *bip32_path, - size_t bip32_path_len, - char *out, - size_t out_len) { +bool bip32_path_format(const uint32_t *bip32_path, size_t bip32_path_len, char *out, size_t out_len) +{ if (bip32_path_len == 0 || bip32_path_len > MAX_BIP32_PATH) { return false; } diff --git a/lib_standard_app/bip32.h b/lib_standard_app/bip32.h index 3e2491e1b..f2882f197 100644 --- a/lib_standard_app/bip32.h +++ b/lib_standard_app/bip32.h @@ -42,6 +42,6 @@ bool bip32_path_read(const uint8_t *in, size_t in_len, uint32_t *out, size_t out * */ bool bip32_path_format(const uint32_t *bip32_path, - size_t bip32_path_len, - char *out, - size_t out_len); + size_t bip32_path_len, + char *out, + size_t out_len); diff --git a/lib_standard_app/buffer.c b/lib_standard_app/buffer.c index 9d97c0756..96071a201 100644 --- a/lib_standard_app/buffer.c +++ b/lib_standard_app/buffer.c @@ -24,11 +24,13 @@ #include "varint.h" #include "bip32.h" -bool buffer_can_read(const buffer_t *buffer, size_t n) { +bool buffer_can_read(const buffer_t *buffer, size_t n) +{ return buffer->size - buffer->offset >= n; } -bool buffer_seek_set(buffer_t *buffer, size_t offset) { +bool buffer_seek_set(buffer_t *buffer, size_t offset) +{ if (offset > buffer->size) { return false; } @@ -38,7 +40,8 @@ bool buffer_seek_set(buffer_t *buffer, size_t offset) { return true; } -bool buffer_seek_cur(buffer_t *buffer, size_t offset) { +bool buffer_seek_cur(buffer_t *buffer, size_t offset) +{ if (buffer->offset + offset < buffer->offset || // overflow buffer->offset + offset > buffer->size) { // exceed buffer size return false; @@ -49,7 +52,8 @@ bool buffer_seek_cur(buffer_t *buffer, size_t offset) { return true; } -bool buffer_seek_end(buffer_t *buffer, size_t offset) { +bool buffer_seek_end(buffer_t *buffer, size_t offset) +{ if (offset > buffer->size) { return false; } @@ -59,7 +63,8 @@ bool buffer_seek_end(buffer_t *buffer, size_t offset) { return true; } -bool buffer_read_u8(buffer_t *buffer, uint8_t *value) { +bool buffer_read_u8(buffer_t *buffer, uint8_t *value) +{ if (!buffer_can_read(buffer, 1)) { *value = 0; @@ -72,7 +77,8 @@ bool buffer_read_u8(buffer_t *buffer, uint8_t *value) { return true; } -bool buffer_read_u16(buffer_t *buffer, uint16_t *value, endianness_t endianness) { +bool buffer_read_u16(buffer_t *buffer, uint16_t *value, endianness_t endianness) +{ if (!buffer_can_read(buffer, 2)) { *value = 0; @@ -87,7 +93,8 @@ bool buffer_read_u16(buffer_t *buffer, uint16_t *value, endianness_t endianness) return true; } -bool buffer_read_u32(buffer_t *buffer, uint32_t *value, endianness_t endianness) { +bool buffer_read_u32(buffer_t *buffer, uint32_t *value, endianness_t endianness) +{ if (!buffer_can_read(buffer, 4)) { *value = 0; @@ -102,7 +109,8 @@ bool buffer_read_u32(buffer_t *buffer, uint32_t *value, endianness_t endianness) return true; } -bool buffer_read_u64(buffer_t *buffer, uint64_t *value, endianness_t endianness) { +bool buffer_read_u64(buffer_t *buffer, uint64_t *value, endianness_t endianness) +{ if (!buffer_can_read(buffer, 8)) { *value = 0; @@ -117,7 +125,8 @@ bool buffer_read_u64(buffer_t *buffer, uint64_t *value, endianness_t endianness) return true; } -bool buffer_read_varint(buffer_t *buffer, uint64_t *value) { +bool buffer_read_varint(buffer_t *buffer, uint64_t *value) +{ int length = varint_read(buffer->ptr + buffer->offset, buffer->size - buffer->offset, value); if (length < 0) { @@ -129,11 +138,10 @@ bool buffer_read_varint(buffer_t *buffer, uint64_t *value) { return buffer_seek_cur(buffer, (size_t) length); } -bool buffer_read_bip32_path(buffer_t *buffer, uint32_t *out, size_t out_len) { - if (!bip32_path_read(buffer->ptr + buffer->offset, - buffer->size - buffer->offset, - out, - out_len)) { +bool buffer_read_bip32_path(buffer_t *buffer, uint32_t *out, size_t out_len) +{ + if (!bip32_path_read( + buffer->ptr + buffer->offset, buffer->size - buffer->offset, out, out_len)) { return false; } @@ -142,7 +150,8 @@ bool buffer_read_bip32_path(buffer_t *buffer, uint32_t *out, size_t out_len) { return true; } -bool buffer_copy(const buffer_t *buffer, uint8_t *out, size_t out_len) { +bool buffer_copy(const buffer_t *buffer, uint8_t *out, size_t out_len) +{ if (buffer->size - buffer->offset > out_len) { return false; } @@ -152,7 +161,8 @@ bool buffer_copy(const buffer_t *buffer, uint8_t *out, size_t out_len) { return true; } -bool buffer_move(buffer_t *buffer, uint8_t *out, size_t out_len) { +bool buffer_move(buffer_t *buffer, uint8_t *out, size_t out_len) +{ if (!buffer_copy(buffer, out, out_len)) { return false; } diff --git a/lib_standard_app/buffer.h b/lib_standard_app/buffer.h index ae3e82937..6b31ab0b2 100644 --- a/lib_standard_app/buffer.h +++ b/lib_standard_app/buffer.h @@ -16,9 +16,9 @@ typedef enum { * Struct for buffer with size and offset. */ typedef struct { - const uint8_t *ptr; /// Pointer to byte buffer - size_t size; /// Size of byte buffer - size_t offset; /// Offset in byte buffer + const uint8_t *ptr; /// Pointer to byte buffer + size_t size; /// Size of byte buffer + size_t offset; /// Offset in byte buffer } buffer_t; /** diff --git a/lib_standard_app/crypto_helpers.c b/lib_standard_app/crypto_helpers.c index 4a6428bf5..fb6054951 100644 --- a/lib_standard_app/crypto_helpers.c +++ b/lib_standard_app/crypto_helpers.c @@ -21,18 +21,19 @@ #include "cx.h" #include "os.h" -WARN_UNUSED_RESULT cx_err_t bip32_derive_with_seed_init_privkey_256( - unsigned int derivation_mode, - cx_curve_t curve, - const uint32_t *path, - size_t path_len, - cx_ecfp_256_private_key_t *privkey, - uint8_t *chain_code, - unsigned char *seed, - size_t seed_len) { +WARN_UNUSED_RESULT cx_err_t +bip32_derive_with_seed_init_privkey_256(unsigned int derivation_mode, + cx_curve_t curve, + const uint32_t *path, + size_t path_len, + cx_ecfp_256_private_key_t *privkey, + uint8_t *chain_code, + unsigned char *seed, + size_t seed_len) +{ cx_err_t error = CX_OK; - uint8_t raw_privkey[64]; // Allocate 64 bytes to respect Syscall API but only 32 will be used - size_t length; + uint8_t raw_privkey[64]; // Allocate 64 bytes to respect Syscall API but only 32 will be used + size_t length; // Check curve key length CX_CHECK(cx_ecdomain_parameters_length(curve, &length)); @@ -42,14 +43,8 @@ WARN_UNUSED_RESULT cx_err_t bip32_derive_with_seed_init_privkey_256( } // Derive private key according to BIP32 path - CX_CHECK(os_derive_bip32_with_seed_no_throw(derivation_mode, - curve, - path, - path_len, - raw_privkey, - chain_code, - seed, - seed_len)); + CX_CHECK(os_derive_bip32_with_seed_no_throw( + derivation_mode, curve, path, path_len, raw_privkey, chain_code, seed, seed_len)); // Init privkey from raw CX_CHECK(cx_ecfp_init_private_key_no_throw(curve, raw_privkey, length, privkey)); @@ -65,30 +60,24 @@ WARN_UNUSED_RESULT cx_err_t bip32_derive_with_seed_init_privkey_256( return error; } -WARN_UNUSED_RESULT cx_err_t bip32_derive_with_seed_get_pubkey_256( - unsigned int derivation_mode, - cx_curve_t curve, - const uint32_t *path, - size_t path_len, - uint8_t raw_pubkey[static 65], - uint8_t *chain_code, - cx_md_t hashID, - unsigned char *seed, - size_t seed_len) { +WARN_UNUSED_RESULT cx_err_t bip32_derive_with_seed_get_pubkey_256(unsigned int derivation_mode, + cx_curve_t curve, + const uint32_t *path, + size_t path_len, + uint8_t raw_pubkey[static 65], + uint8_t *chain_code, + cx_md_t hashID, + unsigned char *seed, + size_t seed_len) +{ cx_err_t error = CX_OK; cx_ecfp_256_private_key_t privkey; - cx_ecfp_256_public_key_t pubkey; + cx_ecfp_256_public_key_t pubkey; // Derive private key according to BIP32 path - CX_CHECK(bip32_derive_with_seed_init_privkey_256(derivation_mode, - curve, - path, - path_len, - &privkey, - chain_code, - seed, - seed_len)); + CX_CHECK(bip32_derive_with_seed_init_privkey_256( + derivation_mode, curve, path, path_len, &privkey, chain_code, seed, seed_len)); // Generate associated pubkey CX_CHECK(cx_ecfp_generate_pair2_no_throw(curve, &pubkey, &privkey, true, hashID)); @@ -111,35 +100,30 @@ WARN_UNUSED_RESULT cx_err_t bip32_derive_with_seed_get_pubkey_256( return error; } -WARN_UNUSED_RESULT cx_err_t bip32_derive_with_seed_ecdsa_sign_hash_256( - unsigned int derivation_mode, - cx_curve_t curve, - const uint32_t *path, - size_t path_len, - uint32_t sign_mode, - cx_md_t hashID, - const uint8_t *hash, - size_t hash_len, - uint8_t *sig, - size_t *sig_len, - uint32_t *info, - unsigned char *seed, - size_t seed_len) { - cx_err_t error = CX_OK; +WARN_UNUSED_RESULT cx_err_t bip32_derive_with_seed_ecdsa_sign_hash_256(unsigned int derivation_mode, + cx_curve_t curve, + const uint32_t *path, + size_t path_len, + uint32_t sign_mode, + cx_md_t hashID, + const uint8_t *hash, + size_t hash_len, + uint8_t *sig, + size_t *sig_len, + uint32_t *info, + unsigned char *seed, + size_t seed_len) +{ + cx_err_t error = CX_OK; cx_ecfp_256_private_key_t privkey; - size_t buf_len = *sig_len; + size_t buf_len = *sig_len; // Derive private key according to BIP32 path - CX_CHECK(bip32_derive_with_seed_init_privkey_256(derivation_mode, - curve, - path, - path_len, - &privkey, - NULL, - seed, - seed_len)); + CX_CHECK(bip32_derive_with_seed_init_privkey_256( + derivation_mode, curve, path, path_len, &privkey, NULL, seed, seed_len)); - CX_CHECK(cx_ecdsa_sign_no_throw(&privkey, sign_mode, hashID, hash, hash_len, sig, sig_len, info)); + CX_CHECK( + cx_ecdsa_sign_no_throw(&privkey, sign_mode, hashID, hash, hash_len, sig, sig_len, info)); end: explicit_bzero(&privkey, sizeof(privkey)); @@ -152,22 +136,22 @@ WARN_UNUSED_RESULT cx_err_t bip32_derive_with_seed_ecdsa_sign_hash_256( return error; } -WARN_UNUSED_RESULT cx_err_t bip32_derive_with_seed_eddsa_sign_hash_256( - unsigned int derivation_mode, - cx_curve_t curve, - const uint32_t *path, - size_t path_len, - cx_md_t hashID, - const uint8_t *hash, - size_t hash_len, - uint8_t *sig, - size_t *sig_len, - unsigned char *seed, - size_t seed_len) { - cx_err_t error = CX_OK; +WARN_UNUSED_RESULT cx_err_t bip32_derive_with_seed_eddsa_sign_hash_256(unsigned int derivation_mode, + cx_curve_t curve, + const uint32_t *path, + size_t path_len, + cx_md_t hashID, + const uint8_t *hash, + size_t hash_len, + uint8_t *sig, + size_t *sig_len, + unsigned char *seed, + size_t seed_len) +{ + cx_err_t error = CX_OK; cx_ecfp_256_private_key_t privkey; - size_t size; - size_t buf_len = *sig_len; + size_t size; + size_t buf_len = *sig_len; if (sig_len == NULL) { error = CX_INVALID_PARAMETER_VALUE; @@ -175,14 +159,8 @@ WARN_UNUSED_RESULT cx_err_t bip32_derive_with_seed_eddsa_sign_hash_256( } // Derive private key according to BIP32 path - CX_CHECK(bip32_derive_with_seed_init_privkey_256(derivation_mode, - curve, - path, - path_len, - &privkey, - NULL, - seed, - seed_len)); + CX_CHECK(bip32_derive_with_seed_init_privkey_256( + derivation_mode, curve, path, path_len, &privkey, NULL, seed, seed_len)); CX_CHECK(cx_eddsa_sign_no_throw(&privkey, hashID, hash, hash_len, sig, *sig_len)); diff --git a/lib_standard_app/crypto_helpers.h b/lib_standard_app/crypto_helpers.h index 7b2a4e5d2..beeafc940 100644 --- a/lib_standard_app/crypto_helpers.h +++ b/lib_standard_app/crypto_helpers.h @@ -29,15 +29,15 @@ * - CX_EC_INVALID_CURVE * - CX_INTERNAL_ERROR */ -WARN_UNUSED_RESULT cx_err_t bip32_derive_with_seed_init_privkey_256( - unsigned int derivation_mode, - cx_curve_t curve, - const uint32_t *path, - size_t path_len, - cx_ecfp_256_private_key_t *privkey, - uint8_t *chain_code, - unsigned char *seed, - size_t seed_len); +WARN_UNUSED_RESULT cx_err_t +bip32_derive_with_seed_init_privkey_256(unsigned int derivation_mode, + cx_curve_t curve, + const uint32_t *path, + size_t path_len, + cx_ecfp_256_private_key_t *privkey, + uint8_t *chain_code, + unsigned char *seed, + size_t seed_len); /** * @brief Gets the private key from the device seed using the specified bip32 path. @@ -58,19 +58,14 @@ WARN_UNUSED_RESULT cx_err_t bip32_derive_with_seed_init_privkey_256( * - CX_INTERNAL_ERROR */ WARN_UNUSED_RESULT static inline cx_err_t bip32_derive_init_privkey_256( - cx_curve_t curve, - const uint32_t *path, - size_t path_len, - cx_ecfp_256_private_key_t *privkey, - uint8_t *chain_code) { - return bip32_derive_with_seed_init_privkey_256(HDW_NORMAL, - curve, - path, - path_len, - privkey, - chain_code, - NULL, - 0); + cx_curve_t curve, + const uint32_t *path, + size_t path_len, + cx_ecfp_256_private_key_t *privkey, + uint8_t *chain_code) +{ + return bip32_derive_with_seed_init_privkey_256( + HDW_NORMAL, curve, path, path_len, privkey, chain_code, NULL, 0); } /** @@ -99,16 +94,15 @@ WARN_UNUSED_RESULT static inline cx_err_t bip32_derive_init_privkey_256( * - CX_EC_INVALID_CURVE * - CX_INTERNAL_ERROR */ -WARN_UNUSED_RESULT cx_err_t bip32_derive_with_seed_get_pubkey_256( - unsigned int derivation_mode, - cx_curve_t curve, - const uint32_t *path, - size_t path_len, - uint8_t raw_pubkey[static 65], - uint8_t *chain_code, - cx_md_t hashID, - unsigned char *seed, - size_t seed_len); +WARN_UNUSED_RESULT cx_err_t bip32_derive_with_seed_get_pubkey_256(unsigned int derivation_mode, + cx_curve_t curve, + const uint32_t *path, + size_t path_len, + uint8_t raw_pubkey[static 65], + uint8_t *chain_code, + cx_md_t hashID, + unsigned char *seed, + size_t seed_len); /** * @brief Gets the public key from the device seed using the specified bip32 path. @@ -130,26 +124,20 @@ WARN_UNUSED_RESULT cx_err_t bip32_derive_with_seed_get_pubkey_256( * - CX_EC_INVALID_CURVE * - CX_INTERNAL_ERROR */ -WARN_UNUSED_RESULT static inline cx_err_t bip32_derive_get_pubkey_256( - cx_curve_t curve, - const uint32_t *path, - size_t path_len, - uint8_t raw_pubkey[static 65], - uint8_t *chain_code, - cx_md_t hashID) { - return bip32_derive_with_seed_get_pubkey_256(HDW_NORMAL, - curve, - path, - path_len, - raw_pubkey, - chain_code, - hashID, - NULL, - 0); +WARN_UNUSED_RESULT static inline cx_err_t bip32_derive_get_pubkey_256(cx_curve_t curve, + const uint32_t *path, + size_t path_len, + uint8_t raw_pubkey[static 65], + uint8_t *chain_code, + cx_md_t hashID) +{ + return bip32_derive_with_seed_get_pubkey_256( + HDW_NORMAL, curve, path, path_len, raw_pubkey, chain_code, hashID, NULL, 0); } /** - * @brief Sign a hash with ecdsa using the device seed derived from the specified bip32 path and seed key. + * @brief Sign a hash with ecdsa using the device seed derived from the specified bip32 path and + * seed key. * * @param[in] derivation_mode Derivation mode, one of HDW_NORMAL / HDW_ED25519_SLIP10 / HDW_SLIP21. * @@ -168,11 +156,13 @@ WARN_UNUSED_RESULT static inline cx_err_t bip32_derive_get_pubkey_256( * @param[in] hash_len Length of the digest in octets. * * @param[out] sig Buffer where to store the signature. - * The signature is encoded in TLV: **30 || L || 02 || Lr || r || 02 || Ls || s** + * The signature is encoded in TLV: **30 || L || 02 || Lr || r || 02 || + * Ls || s** * * @param[in] sig_len Length of the signature buffer, updated with signature length. * - * @param[out] info Set with CX_ECCINFO_PARITY_ODD if the y-coordinate is odd when computing **[k].G**. + * @param[out] info Set with CX_ECCINFO_PARITY_ODD if the y-coordinate is odd when + * computing **[k].G**. * * @param[in] seed Seed key to use for derivation. * @@ -183,20 +173,19 @@ WARN_UNUSED_RESULT static inline cx_err_t bip32_derive_get_pubkey_256( * - CX_EC_INVALID_CURVE * - CX_INTERNAL_ERROR */ -WARN_UNUSED_RESULT cx_err_t bip32_derive_with_seed_ecdsa_sign_hash_256( - unsigned int derivation_mode, - cx_curve_t curve, - const uint32_t *path, - size_t path_len, - uint32_t sign_mode, - cx_md_t hashID, - const uint8_t *hash, - size_t hash_len, - uint8_t *sig, - size_t *sig_len, - uint32_t *info, - unsigned char *seed, - size_t seed_len); +WARN_UNUSED_RESULT cx_err_t bip32_derive_with_seed_ecdsa_sign_hash_256(unsigned int derivation_mode, + cx_curve_t curve, + const uint32_t *path, + size_t path_len, + uint32_t sign_mode, + cx_md_t hashID, + const uint8_t *hash, + size_t hash_len, + uint8_t *sig, + size_t *sig_len, + uint32_t *info, + unsigned char *seed, + size_t seed_len); /** * @brief Sign a hash with ecdsa using the device seed derived from the specified bip32 path. @@ -218,28 +207,30 @@ WARN_UNUSED_RESULT cx_err_t bip32_derive_with_seed_ecdsa_sign_hash_256( * @param[in] hash_len Length of the digest in octets. * * @param[out] sig Buffer where to store the signature. - * The signature is encoded in TLV: **30 || L || 02 || Lr || r || 02 || Ls || s** + * The signature is encoded in TLV: **30 || L || 02 || Lr || r || 02 || + * Ls || s** * * @param[in] sig_len Length of the signature buffer, updated with signature length. * - * @param[out] info Set with CX_ECCINFO_PARITY_ODD if the y-coordinate is odd when computing **[k].G**. + * @param[out] info Set with CX_ECCINFO_PARITY_ODD if the y-coordinate is odd when + * computing **[k].G**. * * @return Error code: * - CX_OK on success * - CX_EC_INVALID_CURVE * - CX_INTERNAL_ERROR */ -WARN_UNUSED_RESULT static inline cx_err_t bip32_derive_ecdsa_sign_hash_256( - cx_curve_t curve, - const uint32_t *path, - size_t path_len, - uint32_t sign_mode, - cx_md_t hashID, - const uint8_t *hash, - size_t hash_len, - uint8_t *sig, - size_t *sig_len, - uint32_t *info) { +WARN_UNUSED_RESULT static inline cx_err_t bip32_derive_ecdsa_sign_hash_256(cx_curve_t curve, + const uint32_t *path, + size_t path_len, + uint32_t sign_mode, + cx_md_t hashID, + const uint8_t *hash, + size_t hash_len, + uint8_t *sig, + size_t *sig_len, + uint32_t *info) +{ return bip32_derive_with_seed_ecdsa_sign_hash_256(HDW_NORMAL, curve, path, @@ -256,7 +247,8 @@ WARN_UNUSED_RESULT static inline cx_err_t bip32_derive_ecdsa_sign_hash_256( } /** - * @brief Sign a hash with eddsa using the device seed derived from the specified bip32 path and seed key. + * @brief Sign a hash with eddsa using the device seed derived from the specified bip32 path and + * seed key. * * @param[in] derivation_mode Derivation mode, one of HDW_NORMAL / HDW_ED25519_SLIP10 / HDW_SLIP21. * @@ -287,18 +279,17 @@ WARN_UNUSED_RESULT static inline cx_err_t bip32_derive_ecdsa_sign_hash_256( * - CX_EC_INVALID_CURVE * - CX_INTERNAL_ERROR */ -WARN_UNUSED_RESULT cx_err_t bip32_derive_with_seed_eddsa_sign_hash_256( - unsigned int derivation_mode, - cx_curve_t curve, - const uint32_t *path, - size_t path_len, - cx_md_t hashID, - const uint8_t *hash, - size_t hash_len, - uint8_t *sig, - size_t *sig_len, - unsigned char *seed, - size_t seed_len); +WARN_UNUSED_RESULT cx_err_t bip32_derive_with_seed_eddsa_sign_hash_256(unsigned int derivation_mode, + cx_curve_t curve, + const uint32_t *path, + size_t path_len, + cx_md_t hashID, + const uint8_t *hash, + size_t hash_len, + uint8_t *sig, + size_t *sig_len, + unsigned char *seed, + size_t seed_len); /** * @brief Sign a hash with eddsa using the device seed derived from the specified bip32 path. @@ -326,24 +317,15 @@ WARN_UNUSED_RESULT cx_err_t bip32_derive_with_seed_eddsa_sign_hash_256( * - CX_EC_INVALID_CURVE * - CX_INTERNAL_ERROR */ -WARN_UNUSED_RESULT static inline cx_err_t bip32_derive_eddsa_sign_hash_256( - cx_curve_t curve, - const uint32_t *path, - size_t path_len, - cx_md_t hashID, - const uint8_t *hash, - size_t hash_len, - uint8_t *sig, - size_t *sig_len) { - return bip32_derive_with_seed_eddsa_sign_hash_256(HDW_NORMAL, - curve, - path, - path_len, - hashID, - hash, - hash_len, - sig, - sig_len, - NULL, - 0); +WARN_UNUSED_RESULT static inline cx_err_t bip32_derive_eddsa_sign_hash_256(cx_curve_t curve, + const uint32_t *path, + size_t path_len, + cx_md_t hashID, + const uint8_t *hash, + size_t hash_len, + uint8_t *sig, + size_t *sig_len) +{ + return bip32_derive_with_seed_eddsa_sign_hash_256( + HDW_NORMAL, curve, path, path_len, hashID, hash, hash_len, sig, sig_len, NULL, 0); } diff --git a/lib_standard_app/debug.c b/lib_standard_app/debug.c index 60ba8d7b4..ea1a396cb 100644 --- a/lib_standard_app/debug.c +++ b/lib_standard_app/debug.c @@ -27,15 +27,13 @@ #ifdef HAVE_DEBUG_THROWS static char errordata[20]; -WEAK void app_throw_info(unsigned int exception, unsigned int lr_val) { - snprintf(errordata, - sizeof(errordata), - "n%d, LR=0x%08X", - exception, - lr_val); +WEAK void app_throw_info(unsigned int exception, unsigned int lr_val) +{ + snprintf(errordata, sizeof(errordata), "n%d, LR=0x%08X", exception, lr_val); } -static void review_choice(bool confirm) { +static void review_choice(bool confirm) +{ UNUSED(confirm); os_sched_exit(-1); } @@ -45,13 +43,14 @@ UX_STEP_CB(ux_error, bnnn_paging, review_choice(true), { - .title = "App error", - .text = errordata, + .title = "App error", + .text = errordata, }); UX_FLOW(ux_error_flow, &ux_error); #endif -WEAK void __attribute__((noreturn)) debug_display_throw_error(int exception) { +WEAK void __attribute__((noreturn)) debug_display_throw_error(int exception) +{ UNUSED(exception); #ifdef HAVE_BAGL @@ -59,12 +58,8 @@ WEAK void __attribute__((noreturn)) debug_display_throw_error(int exception) { #endif #ifdef HAVE_NBGL - nbgl_useCaseChoice(&C_round_warning_64px, - "App error", - errordata, - "Exit app", - "Exit app", - review_choice); + nbgl_useCaseChoice( + &C_round_warning_64px, "App error", errordata, "Exit app", "Exit app", review_choice); #endif // Block until the user approve and the app is quit diff --git a/lib_standard_app/format.c b/lib_standard_app/format.c index a38d5e4e8..a9c165308 100644 --- a/lib_standard_app/format.c +++ b/lib_standard_app/format.c @@ -21,12 +21,13 @@ #include "format.h" -bool format_i64(char *dst, size_t dst_len, const int64_t value) { +bool format_i64(char *dst, size_t dst_len, const int64_t value) +{ char temp[] = "-9223372036854775808"; - char *ptr = temp; - int64_t num = value; - int sign = 1; + char *ptr = temp; + int64_t num = value; + int sign = 1; if (value < 0) { sign = -1; @@ -39,7 +40,8 @@ bool format_i64(char *dst, size_t dst_len, const int64_t value) { if (value < 0) { *ptr++ = '-'; - } else if (value == 0) { + } + else if (value == 0) { *ptr++ = '0'; } @@ -60,7 +62,8 @@ bool format_i64(char *dst, size_t dst_len, const int64_t value) { return true; } -bool format_u64(char *out, size_t outLen, uint64_t in) { +bool format_u64(char *out, size_t outLen, uint64_t in) +{ size_t i = 0; if (outLen == 0) { @@ -76,16 +79,16 @@ bool format_u64(char *out, size_t outLen, uint64_t in) { return false; } } - out[i] = in + '0'; + out[i] = in + '0'; out[i + 1] = '\0'; uint8_t j = 0; - char tmp; + char tmp; // revert the string while (j < i) { // swap out[j] and out[i] - tmp = out[j]; + tmp = out[j]; out[j] = out[i]; out[i] = tmp; @@ -95,7 +98,8 @@ bool format_u64(char *out, size_t outLen, uint64_t in) { return true; } -bool format_fpu64(char *dst, size_t dst_len, const uint64_t value, uint8_t decimals) { +bool format_fpu64(char *dst, size_t dst_len, const uint64_t value, uint8_t decimals) +{ char buffer[21] = {0}; if (!format_u64(buffer, sizeof(buffer), value)) { @@ -115,7 +119,8 @@ bool format_fpu64(char *dst, size_t dst_len, const uint64_t value, uint8_t decim } dst_len -= 2 + decimals - digits; strncpy(dst, buffer, dst_len); - } else { + } + else { if (dst_len <= digits + 1 + decimals) { return false; } @@ -129,7 +134,8 @@ bool format_fpu64(char *dst, size_t dst_len, const uint64_t value, uint8_t decim return true; } -bool format_fpu64_trimmed(char *dst, size_t dst_len, const uint64_t value, uint8_t decimals) { +bool format_fpu64_trimmed(char *dst, size_t dst_len, const uint64_t value, uint8_t decimals) +{ if (!format_fpu64(dst, dst_len, value, decimals)) { return false; } @@ -147,22 +153,23 @@ bool format_fpu64_trimmed(char *dst, size_t dst_len, const uint64_t value, uint8 return true; } -int format_hex(const uint8_t *in, size_t in_len, char *out, size_t out_len) { +int format_hex(const uint8_t *in, size_t in_len, char *out, size_t out_len) +{ if (out_len < 2 * in_len + 1) { return -1; } - const char hex[] = "0123456789ABCDEF"; - size_t i = 0; - int written = 0; + const char hex[] = "0123456789ABCDEF"; + size_t i = 0; + int written = 0; while (i < in_len && (i * 2 + (2 + 1)) <= out_len) { uint8_t high_nibble = (in[i] & 0xF0) >> 4; - *out = hex[high_nibble]; + *out = hex[high_nibble]; out++; uint8_t low_nibble = in[i] & 0x0F; - *out = hex[low_nibble]; + *out = hex[low_nibble]; out++; i++; diff --git a/lib_standard_app/io.c b/lib_standard_app/io.c index 6eb4199b1..b403be6fe 100644 --- a/lib_standard_app/io.c +++ b/lib_standard_app/io.c @@ -42,18 +42,18 @@ static uint32_t G_output_len = 0; */ static io_state_e G_io_state = READY; - #ifdef HAVE_BAGL -WEAK void io_seproxyhal_display(const bagl_element_t *element) { +WEAK void io_seproxyhal_display(const bagl_element_t *element) +{ io_seproxyhal_display_default(element); } #endif // HAVE_BAGL // This function can be used to declare a callback to SEPROXYHAL_TAG_TICKER_EVENT in the application -WEAK void app_ticker_event_callback(void) { -} +WEAK void app_ticker_event_callback(void) {} -WEAK uint8_t io_event(uint8_t channel) { +WEAK uint8_t io_event(uint8_t channel) +{ (void) channel; switch (G_io_seproxyhal_spi_buffer[0]) { @@ -68,7 +68,7 @@ WEAK uint8_t io_event(uint8_t channel) { SEPROXYHAL_TAG_STATUS_EVENT_FLAG_USB_POWERED)) { THROW(EXCEPTION_IO_RESET); } - __attribute__((fallthrough)); + __attribute__((fallthrough)); case SEPROXYHAL_TAG_DISPLAY_PROCESSED_EVENT: #ifdef HAVE_BAGL UX_DISPLAYED_EVENT({}); @@ -98,7 +98,8 @@ WEAK uint8_t io_event(uint8_t channel) { return 1; } -WEAK uint16_t io_exchange_al(uint8_t channel, uint16_t tx_len) { +WEAK uint16_t io_exchange_al(uint8_t channel, uint16_t tx_len) +{ switch (channel & ~(IO_FLAGS)) { case CHANNEL_KEYBOARD: break; @@ -111,7 +112,8 @@ WEAK uint16_t io_exchange_al(uint8_t channel, uint16_t tx_len) { } return 0; - } else { + } + else { return io_seproxyhal_spi_recv(G_io_apdu_buffer, sizeof(G_io_apdu_buffer), 0); } default: @@ -121,39 +123,43 @@ WEAK uint16_t io_exchange_al(uint8_t channel, uint16_t tx_len) { return 0; } -WEAK void io_init() { +WEAK void io_init() +{ // Reset length of APDU response G_output_len = 0; - G_io_state = READY; + G_io_state = READY; } -WEAK int io_recv_command() { +WEAK int io_recv_command() +{ int ret = -1; switch (G_io_state) { case READY: G_io_state = RECEIVED; - ret = io_exchange(CHANNEL_APDU, G_output_len); + ret = io_exchange(CHANNEL_APDU, G_output_len); break; case RECEIVED: G_io_state = WAITING; - ret = io_exchange(CHANNEL_APDU | IO_ASYNCH_REPLY, G_output_len); + ret = io_exchange(CHANNEL_APDU | IO_ASYNCH_REPLY, G_output_len); G_io_state = RECEIVED; break; case WAITING: G_io_state = READY; - ret = -1; + ret = -1; break; } return ret; } -WEAK int io_send_response_pointer(const uint8_t *ptr, size_t size, uint16_t sw) { +WEAK int io_send_response_pointer(const uint8_t *ptr, size_t size, uint16_t sw) +{ return io_send_response_buffer(&(const buffer_t){.ptr = ptr, .size = size, .offset = 0}, sw); } -WEAK int io_send_response_buffer(const buffer_t *rdata, uint16_t sw) { +WEAK int io_send_response_buffer(const buffer_t *rdata, uint16_t sw) +{ int ret = -1; if (rdata != NULL) { @@ -163,7 +169,8 @@ WEAK int io_send_response_buffer(const buffer_t *rdata, uint16_t sw) { } G_output_len = rdata->size - rdata->offset; PRINTF("<= SW=%04X | RData=%.*H\n", sw, rdata->size, rdata->ptr); - } else { + } + else { G_output_len = 0; PRINTF("<= SW=%04X | RData=\n", sw); } @@ -177,12 +184,13 @@ WEAK int io_send_response_buffer(const buffer_t *rdata, uint16_t sw) { PRINTF("Swap answer is processed. Send it\n"); if (io_exchange(CHANNEL_APDU | IO_RETURN_AFTER_TX, G_output_len) == 0) { swap_finalize_exchange_sign_transaction(sw == SW_OK); - } else { + } + else { PRINTF("Unrecoverable\n"); os_sched_exit(-1); } } -#endif // HAVE_SWAP +#endif // HAVE_SWAP switch (G_io_state) { case READY: @@ -190,18 +198,19 @@ WEAK int io_send_response_buffer(const buffer_t *rdata, uint16_t sw) { break; case RECEIVED: G_io_state = READY; - ret = 0; + ret = 0; break; case WAITING: - ret = io_exchange(CHANNEL_APDU | IO_RETURN_AFTER_TX, G_output_len); + ret = io_exchange(CHANNEL_APDU | IO_RETURN_AFTER_TX, G_output_len); G_output_len = 0; - G_io_state = READY; + G_io_state = READY; break; } return ret; } -WEAK int io_send_sw(uint16_t sw) { +WEAK int io_send_sw(uint16_t sw) +{ return io_send_response_buffer(NULL, sw); } diff --git a/lib_standard_app/main.c b/lib_standard_app/main.c index e2e2ea1d4..80cf336c7 100644 --- a/lib_standard_app/main.c +++ b/lib_standard_app/main.c @@ -26,20 +26,22 @@ #ifdef HAVE_NBGL #include "nbgl_use_case.h" -#endif // HAVE_NBGL -#endif // HAVE_SWAP +#endif // HAVE_NBGL +#endif // HAVE_SWAP -ux_state_t G_ux; +ux_state_t G_ux; bolos_ux_params_t G_ux_params; /** * Exit the application and go back to the dashboard. */ -WEAK void __attribute__((noreturn)) app_exit(void) { +WEAK void __attribute__((noreturn)) app_exit(void) +{ os_sched_exit(-1); } -static void common_app_init(void) { +static void common_app_init(void) +{ UX_INIT(); io_seproxyhal_init(); @@ -50,22 +52,26 @@ static void common_app_init(void) { #ifdef HAVE_BLE BLE_power(0, NULL); BLE_power(1, NULL); -#endif // HAVE_BLE +#endif // HAVE_BLE } -static void standalone_app_main(void) { +static void standalone_app_main(void) +{ #ifdef HAVE_SWAP - G_called_from_swap = false; + G_called_from_swap = false; G_swap_response_ready = false; -#endif // HAVE_SWAP +#endif // HAVE_SWAP - BEGIN_TRY { - TRY { + BEGIN_TRY + { + TRY + { common_app_init(); app_main(); } - CATCH_OTHER(e) { + CATCH_OTHER(e) + { PRINTF("Exiting following exception: %d\n", e); #ifdef HAVE_DEBUG_THROWS @@ -87,8 +93,7 @@ static void standalone_app_main(void) { debug_display_throw_error(e); #endif } - FINALLY { - } + FINALLY {} } END_TRY; @@ -97,26 +102,28 @@ static void standalone_app_main(void) { } #ifdef HAVE_SWAP -static void library_app_main(libargs_t *args) { - BEGIN_TRY { - TRY { +static void library_app_main(libargs_t *args) +{ + BEGIN_TRY + { + TRY + { PRINTF("Inside library\n"); switch (args->command) { - case SIGN_TRANSACTION: - { - // Backup up transaction parameters and wipe BSS to avoid collusion with app-exchange - // BSS data. + case SIGN_TRANSACTION: { + // Backup up transaction parameters and wipe BSS to avoid collusion with + // app-exchange BSS data. bool success = swap_copy_transaction_parameters(args->create_transaction); if (success) { // BSS was wiped, we can now init these globals - G_called_from_swap = true; + G_called_from_swap = true; G_swap_response_ready = false; common_app_init(); #ifdef HAVE_NBGL nbgl_useCaseSpinner("Signing"); -#endif // HAVE_NBGL +#endif // HAVE_NBGL app_main(); } @@ -132,18 +139,21 @@ static void library_app_main(libargs_t *args) { break; } } - CATCH_OTHER(e) { + CATCH_OTHER(e) + { PRINTF("Exiting following exception: %d\n", e); } - FINALLY { + FINALLY + { os_lib_end(); } } END_TRY; } -#endif // HAVE_SWAP +#endif // HAVE_SWAP -__attribute__((section(".boot"))) int main(int arg0) { +__attribute__((section(".boot"))) int main(int arg0) +{ // exit critical section __asm volatile("cpsie i"); @@ -160,11 +170,12 @@ __attribute__((section(".boot"))) int main(int arg0) { libargs_t *args = (libargs_t *) arg0; if (args->id == 0x100) { library_app_main(args); - } else { + } + else { app_exit(); } } -#endif // HAVE_SWAP +#endif // HAVE_SWAP return 0; } diff --git a/lib_standard_app/offsets.h b/lib_standard_app/offsets.h index 3db4bc148..86336311f 100644 --- a/lib_standard_app/offsets.h +++ b/lib_standard_app/offsets.h @@ -3,23 +3,23 @@ /** * Offset of instruction class. */ -#define OFFSET_CLA 0 +#define OFFSET_CLA 0 /** * Offset of instruction code. */ -#define OFFSET_INS 1 +#define OFFSET_INS 1 /** * Offset of instruction parameter 1. */ -#define OFFSET_P1 2 +#define OFFSET_P1 2 /** * Offset of instruction parameter 2. */ -#define OFFSET_P2 3 +#define OFFSET_P2 3 /** * Offset of command data length. */ -#define OFFSET_LC 4 +#define OFFSET_LC 4 /** * Offset of command data. */ diff --git a/lib_standard_app/parser.c b/lib_standard_app/parser.c index 06beb32ab..e0a4fefc2 100644 --- a/lib_standard_app/parser.c +++ b/lib_standard_app/parser.c @@ -22,7 +22,8 @@ #include "parser.h" #include "offsets.h" -bool apdu_parser(command_t *cmd, uint8_t *buf, size_t buf_len) { +bool apdu_parser(command_t *cmd, uint8_t *buf, size_t buf_len) +{ // Check minimum length, CLA / INS / P1 and P2 are mandatory if (buf_len < OFFSET_LC) { return false; @@ -31,7 +32,8 @@ bool apdu_parser(command_t *cmd, uint8_t *buf, size_t buf_len) { if (buf_len == OFFSET_LC) { // Lc field not specified, implies lc = 0 cmd->lc = 0; - } else { + } + else { // Lc field specified, check value against received length cmd->lc = buf[OFFSET_LC]; if (buf_len - OFFSET_CDATA != cmd->lc) { @@ -39,10 +41,10 @@ bool apdu_parser(command_t *cmd, uint8_t *buf, size_t buf_len) { } } - cmd->cla = buf[OFFSET_CLA]; - cmd->ins = buf[OFFSET_INS]; - cmd->p1 = buf[OFFSET_P1]; - cmd->p2 = buf[OFFSET_P2]; + cmd->cla = buf[OFFSET_CLA]; + cmd->ins = buf[OFFSET_INS]; + cmd->p1 = buf[OFFSET_P1]; + cmd->p2 = buf[OFFSET_P2]; cmd->data = (cmd->lc > 0) ? buf + OFFSET_CDATA : NULL; return true; diff --git a/lib_standard_app/parser.h b/lib_standard_app/parser.h index 4203f310a..965430e1d 100644 --- a/lib_standard_app/parser.h +++ b/lib_standard_app/parser.h @@ -4,16 +4,15 @@ #include // uint*_t #include // bool - /** * Structure with fields of APDU command. */ typedef struct { - uint8_t cla; /// Instruction class - uint8_t ins; /// Instruction code - uint8_t p1; /// Instruction parameter 1 - uint8_t p2; /// Instruction parameter 2 - uint8_t lc; /// Length of command data + uint8_t cla; /// Instruction class + uint8_t ins; /// Instruction code + uint8_t p1; /// Instruction parameter 1 + uint8_t p2; /// Instruction parameter 2 + uint8_t lc; /// Length of command data uint8_t *data; /// Command data } command_t; diff --git a/lib_standard_app/read.c b/lib_standard_app/read.c index c8ee851ff..786fdd406 100644 --- a/lib_standard_app/read.c +++ b/lib_standard_app/read.c @@ -17,19 +17,22 @@ #include // uint*_t #include // size_t -uint16_t read_u16_be(const uint8_t *ptr, size_t offset) { +uint16_t read_u16_be(const uint8_t *ptr, size_t offset) +{ return (uint16_t) ptr[offset + 0] << 8 | // (uint16_t) ptr[offset + 1] << 0; } -uint32_t read_u32_be(const uint8_t *ptr, size_t offset) { +uint32_t read_u32_be(const uint8_t *ptr, size_t offset) +{ return (uint32_t) ptr[offset + 0] << 24 | // (uint32_t) ptr[offset + 1] << 16 | // (uint32_t) ptr[offset + 2] << 8 | // (uint32_t) ptr[offset + 3] << 0; } -uint64_t read_u64_be(const uint8_t *ptr, size_t offset) { +uint64_t read_u64_be(const uint8_t *ptr, size_t offset) +{ return (uint64_t) ptr[offset + 0] << 56 | // (uint64_t) ptr[offset + 1] << 48 | // (uint64_t) ptr[offset + 2] << 40 | // @@ -40,19 +43,22 @@ uint64_t read_u64_be(const uint8_t *ptr, size_t offset) { (uint64_t) ptr[offset + 7] << 0; } -uint16_t read_u16_le(const uint8_t *ptr, size_t offset) { +uint16_t read_u16_le(const uint8_t *ptr, size_t offset) +{ return (uint16_t) ptr[offset + 0] << 0 | // (uint16_t) ptr[offset + 1] << 8; } -uint32_t read_u32_le(const uint8_t *ptr, size_t offset) { +uint32_t read_u32_le(const uint8_t *ptr, size_t offset) +{ return (uint32_t) ptr[offset + 0] << 0 | // (uint32_t) ptr[offset + 1] << 8 | // (uint32_t) ptr[offset + 2] << 16 | // (uint32_t) ptr[offset + 3] << 24; } -uint64_t read_u64_le(const uint8_t *ptr, size_t offset) { +uint64_t read_u64_le(const uint8_t *ptr, size_t offset) +{ return (uint64_t) ptr[offset + 0] << 0 | // (uint64_t) ptr[offset + 1] << 8 | // (uint64_t) ptr[offset + 2] << 16 | // diff --git a/lib_standard_app/swap_entrypoints.h b/lib_standard_app/swap_entrypoints.h index 1f431ddd9..919b8d387 100644 --- a/lib_standard_app/swap_entrypoints.h +++ b/lib_standard_app/swap_entrypoints.h @@ -28,12 +28,12 @@ /* Check check_address_parameters_t.address_to_check against specified parameters. * * Must set params.result to 0 on error, 1 otherwise */ -void swap_handle_check_address(check_address_parameters_t* params); +void swap_handle_check_address(check_address_parameters_t *params); /* Format printable amount including the ticker from specified parameters. * * Must set empty printable_amount on error, printable amount otherwise */ -void swap_handle_get_printable_amount(get_printable_amount_parameters_t* params); +void swap_handle_get_printable_amount(get_printable_amount_parameters_t *params); /* Backup up transaction parameters and wipe BSS to avoid collusion with * app-exchange BSS data. diff --git a/lib_standard_app/swap_lib_calls.h b/lib_standard_app/swap_lib_calls.h index 213d8b21b..90b19c75a 100644 --- a/lib_standard_app/swap_lib_calls.h +++ b/lib_standard_app/swap_lib_calls.h @@ -31,13 +31,13 @@ typedef struct check_address_parameters_s { // IN uint8_t *coin_configuration; - uint8_t coin_configuration_length; + uint8_t coin_configuration_length; // serialized path, segwit, version prefix, hash used, dictionary etc. // fields and serialization format depends on specific coin app uint8_t *address_parameters; - uint8_t address_parameters_length; - char *address_to_check; - char *extra_id_to_check; + uint8_t address_parameters_length; + char *address_to_check; + char *extra_id_to_check; // OUT int result; } check_address_parameters_t; @@ -46,10 +46,10 @@ typedef struct check_address_parameters_s { typedef struct get_printable_amount_parameters_s { // IN uint8_t *coin_configuration; - uint8_t coin_configuration_length; + uint8_t coin_configuration_length; uint8_t *amount; - uint8_t amount_length; - bool is_fee; + uint8_t amount_length; + bool is_fee; // OUT char printable_amount[MAX_PRINTABLE_AMOUNT_SIZE]; } get_printable_amount_parameters_t; @@ -57,13 +57,13 @@ typedef struct get_printable_amount_parameters_s { typedef struct create_transaction_parameters_s { // IN uint8_t *coin_configuration; - uint8_t coin_configuration_length; + uint8_t coin_configuration_length; uint8_t *amount; - uint8_t amount_length; + uint8_t amount_length; uint8_t *fee_amount; - uint8_t fee_amount_length; - char *destination_address; - char *destination_address_extra_id; + uint8_t fee_amount_length; + char *destination_address; + char *destination_address_extra_id; // OUT uint8_t result; } create_transaction_parameters_t; @@ -73,8 +73,8 @@ typedef struct libargs_s { unsigned int command; unsigned int unused; union { - check_address_parameters_t *check_address; - create_transaction_parameters_t *create_transaction; + check_address_parameters_t *check_address; + create_transaction_parameters_t *create_transaction; get_printable_amount_parameters_t *get_printable_amount; }; } libargs_t; diff --git a/lib_standard_app/swap_utils.c b/lib_standard_app/swap_utils.c index be292bb1d..6eddaa919 100644 --- a/lib_standard_app/swap_utils.c +++ b/lib_standard_app/swap_utils.c @@ -23,7 +23,8 @@ volatile bool G_called_from_swap; volatile bool G_swap_response_ready; -bool swap_str_to_u64(const uint8_t* src, size_t length, uint64_t* result) { +bool swap_str_to_u64(const uint8_t *src, size_t length, uint64_t *result) +{ if (length > sizeof(uint64_t)) { return false; } @@ -37,10 +38,11 @@ bool swap_str_to_u64(const uint8_t* src, size_t length, uint64_t* result) { } bool swap_parse_config(const uint8_t *config, - uint8_t config_len, - char *ticker, - uint8_t ticker_buf_len, - uint8_t *decimals) { + uint8_t config_len, + char *ticker, + uint8_t ticker_buf_len, + uint8_t *decimals) +{ uint8_t ticker_len, offset = 0; if (config_len == 0 || config == NULL) { return false; @@ -60,4 +62,4 @@ bool swap_parse_config(const uint8_t *config, return true; } -#endif // HAVE_SWAP +#endif // HAVE_SWAP diff --git a/lib_standard_app/swap_utils.h b/lib_standard_app/swap_utils.h index f8c4d1d38..645dad69c 100644 --- a/lib_standard_app/swap_utils.h +++ b/lib_standard_app/swap_utils.h @@ -24,7 +24,7 @@ extern volatile bool G_swap_response_ready; bool swap_str_to_u64(const uint8_t *src, size_t length, uint64_t *result); bool swap_parse_config(const uint8_t *config, - uint8_t config_len, - char *ticker, - uint8_t ticker_buf_len, - uint8_t *decimals); + uint8_t config_len, + char *ticker, + uint8_t ticker_buf_len, + uint8_t *decimals); diff --git a/lib_standard_app/varint.c b/lib_standard_app/varint.c index d04fbb274..fb199f91f 100644 --- a/lib_standard_app/varint.c +++ b/lib_standard_app/varint.c @@ -22,7 +22,8 @@ #include "write.h" #include "read.h" -uint8_t varint_size(uint64_t value) { +uint8_t varint_size(uint64_t value) +{ if (value <= 0xFC) { return 1; } @@ -38,7 +39,8 @@ uint8_t varint_size(uint64_t value) { return 9; // <= UINT64_MAX } -int varint_read(const uint8_t *in, size_t in_len, uint64_t *value) { +int varint_read(const uint8_t *in, size_t in_len, uint64_t *value) +{ if (in_len < 1) { return -1; } @@ -74,7 +76,8 @@ int varint_read(const uint8_t *in, size_t in_len, uint64_t *value) { return 1; } -int varint_write(uint8_t *out, size_t offset, uint64_t value) { +int varint_write(uint8_t *out, size_t offset, uint64_t value) +{ uint8_t varint_len = varint_size(value); switch (varint_len) { diff --git a/lib_standard_app/write.c b/lib_standard_app/write.c index 90ec141c0..28ff7ee6d 100644 --- a/lib_standard_app/write.c +++ b/lib_standard_app/write.c @@ -17,48 +17,54 @@ #include // uint*_t #include // size_t -void write_u16_be(uint8_t *ptr, size_t offset, uint16_t value) { - ptr[offset + 0] = (uint8_t)(value >> 8); - ptr[offset + 1] = (uint8_t)(value >> 0); +void write_u16_be(uint8_t *ptr, size_t offset, uint16_t value) +{ + ptr[offset + 0] = (uint8_t) (value >> 8); + ptr[offset + 1] = (uint8_t) (value >> 0); } -void write_u32_be(uint8_t *ptr, size_t offset, uint32_t value) { - ptr[offset + 0] = (uint8_t)(value >> 24); - ptr[offset + 1] = (uint8_t)(value >> 16); - ptr[offset + 2] = (uint8_t)(value >> 8); - ptr[offset + 3] = (uint8_t)(value >> 0); +void write_u32_be(uint8_t *ptr, size_t offset, uint32_t value) +{ + ptr[offset + 0] = (uint8_t) (value >> 24); + ptr[offset + 1] = (uint8_t) (value >> 16); + ptr[offset + 2] = (uint8_t) (value >> 8); + ptr[offset + 3] = (uint8_t) (value >> 0); } -void write_u64_be(uint8_t *ptr, size_t offset, uint64_t value) { - ptr[offset + 0] = (uint8_t)(value >> 56); - ptr[offset + 1] = (uint8_t)(value >> 48); - ptr[offset + 2] = (uint8_t)(value >> 40); - ptr[offset + 3] = (uint8_t)(value >> 32); - ptr[offset + 4] = (uint8_t)(value >> 24); - ptr[offset + 5] = (uint8_t)(value >> 16); - ptr[offset + 6] = (uint8_t)(value >> 8); - ptr[offset + 7] = (uint8_t)(value >> 0); +void write_u64_be(uint8_t *ptr, size_t offset, uint64_t value) +{ + ptr[offset + 0] = (uint8_t) (value >> 56); + ptr[offset + 1] = (uint8_t) (value >> 48); + ptr[offset + 2] = (uint8_t) (value >> 40); + ptr[offset + 3] = (uint8_t) (value >> 32); + ptr[offset + 4] = (uint8_t) (value >> 24); + ptr[offset + 5] = (uint8_t) (value >> 16); + ptr[offset + 6] = (uint8_t) (value >> 8); + ptr[offset + 7] = (uint8_t) (value >> 0); } -void write_u16_le(uint8_t *ptr, size_t offset, uint16_t value) { - ptr[offset + 0] = (uint8_t)(value >> 0); - ptr[offset + 1] = (uint8_t)(value >> 8); +void write_u16_le(uint8_t *ptr, size_t offset, uint16_t value) +{ + ptr[offset + 0] = (uint8_t) (value >> 0); + ptr[offset + 1] = (uint8_t) (value >> 8); } -void write_u32_le(uint8_t *ptr, size_t offset, uint32_t value) { - ptr[offset + 0] = (uint8_t)(value >> 0); - ptr[offset + 1] = (uint8_t)(value >> 8); - ptr[offset + 2] = (uint8_t)(value >> 16); - ptr[offset + 3] = (uint8_t)(value >> 24); +void write_u32_le(uint8_t *ptr, size_t offset, uint32_t value) +{ + ptr[offset + 0] = (uint8_t) (value >> 0); + ptr[offset + 1] = (uint8_t) (value >> 8); + ptr[offset + 2] = (uint8_t) (value >> 16); + ptr[offset + 3] = (uint8_t) (value >> 24); } -void write_u64_le(uint8_t *ptr, size_t offset, uint64_t value) { - ptr[offset + 0] = (uint8_t)(value >> 0); - ptr[offset + 1] = (uint8_t)(value >> 8); - ptr[offset + 2] = (uint8_t)(value >> 16); - ptr[offset + 3] = (uint8_t)(value >> 24); - ptr[offset + 4] = (uint8_t)(value >> 32); - ptr[offset + 5] = (uint8_t)(value >> 40); - ptr[offset + 6] = (uint8_t)(value >> 48); - ptr[offset + 7] = (uint8_t)(value >> 56); +void write_u64_le(uint8_t *ptr, size_t offset, uint64_t value) +{ + ptr[offset + 0] = (uint8_t) (value >> 0); + ptr[offset + 1] = (uint8_t) (value >> 8); + ptr[offset + 2] = (uint8_t) (value >> 16); + ptr[offset + 3] = (uint8_t) (value >> 24); + ptr[offset + 4] = (uint8_t) (value >> 32); + ptr[offset + 5] = (uint8_t) (value >> 40); + ptr[offset + 6] = (uint8_t) (value >> 48); + ptr[offset + 7] = (uint8_t) (value >> 56); } diff --git a/lib_stusb_impl/u2f_impl.c b/lib_stusb_impl/u2f_impl.c index 80acf2917..eec6fc688 100644 --- a/lib_stusb_impl/u2f_impl.c +++ b/lib_stusb_impl/u2f_impl.c @@ -1,20 +1,20 @@ /******************************************************************************* -* Ledger Nano S - Secure firmware -* (c) 2022 Ledger -* -* Licensed under the Apache License, Version 2.0 (the "License"); -* you may not use this file except in compliance with the License. -* You may obtain a copy of the License at -* -* http://www.apache.org/licenses/LICENSE-2.0 -* -* Unless required by applicable law or agreed to in writing, software -* distributed under the License is distributed on an "AS IS" BASIS, -* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -* See the License for the specific language governing permissions and -* limitations under the License. -********************************************************************************/ + * Ledger Nano S - Secure firmware + * (c) 2022 Ledger + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT 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 @@ -27,10 +27,10 @@ #include "u2f_transport.h" #include "u2f_processing.h" -#define INIT_U2F_VERSION 0x02 +#define INIT_U2F_VERSION 0x02 #define INIT_DEVICE_VERSION_MAJOR 0 #define INIT_DEVICE_VERSION_MINOR 1 -#define INIT_BUILD_VERSION 0 +#define INIT_BUILD_VERSION 0 #ifdef HAVE_FIDO2 #define INIT_CAPABILITIES 0x04 @@ -47,19 +47,19 @@ #define APDU_MIN_HEADER 4 #define LC_FIRST_BYTE_OFFSET 4 #define LONG_ENC_LC_SIZE 3 -#define LONG_ENC_LE_SIZE 2 // considering only scenarios where Lc is present +#define LONG_ENC_LE_SIZE 2 // considering only scenarios where Lc is present -#define FIDO_CLA 0x00 -#define FIDO_INS_ENROLL 0x01 -#define FIDO_INS_SIGN 0x02 -#define U2F_HANDLE_SIGN_HEADER_SIZE (32+32+1) -#define FIDO_INS_GET_VERSION 0x03 +#define FIDO_CLA 0x00 +#define FIDO_INS_ENROLL 0x01 +#define FIDO_INS_SIGN 0x02 +#define U2F_HANDLE_SIGN_HEADER_SIZE (32 + 32 + 1) +#define FIDO_INS_GET_VERSION 0x03 -#define FIDO_INS_PROP_GET_COUNTER 0xC0 // U2F_VENDOR_FIRST -#define FIDO_INS_PROP_GET_INFO 0xC1 // grab the max message buffer size on 1 byte +#define FIDO_INS_PROP_GET_COUNTER 0xC0 // U2F_VENDOR_FIRST +#define FIDO_INS_PROP_GET_INFO 0xC1 // grab the max message buffer size on 1 byte #define P1_SIGN_CHECK_ONLY 0x07 -#define P1_SIGN_SIGN 0x03 +#define P1_SIGN_SIGN 0x03 #define SIGN_USER_PRESENCE_MASK 0x01 @@ -67,68 +67,72 @@ static const uint8_t SW_WRONG_LENGTH[] = {0x67, 0x00}; -#else // U2F_PROXY_MAGIC +#else // U2F_PROXY_MAGIC -static const uint8_t SW_BUSY[] = {0x90, 0x01}; +static const uint8_t SW_BUSY[] = {0x90, 0x01}; static const uint8_t SW_PROOF_OF_PRESENCE_REQUIRED[] = {0x69, 0x85}; -static const uint8_t SW_BAD_KEY_HANDLE[] = {0x6A, 0x80}; +static const uint8_t SW_BAD_KEY_HANDLE[] = {0x6A, 0x80}; static const uint8_t SW_UNKNOWN_INSTRUCTION[] = {0x6d, 0x00}; -static const uint8_t SW_UNKNOWN_CLASS[] = {0x6e, 0x00}; -static const uint8_t SW_WRONG_LENGTH[] = {0x67, 0x00}; -static const uint8_t SW_INTERNAL[] = {0x6F, 0x00}; +static const uint8_t SW_UNKNOWN_CLASS[] = {0x6e, 0x00}; +static const uint8_t SW_WRONG_LENGTH[] = {0x67, 0x00}; +static const uint8_t SW_INTERNAL[] = {0x6F, 0x00}; static const uint8_t U2F_VERSION[] = {'U', '2', 'F', '_', 'V', '2', 0x90, 0x00}; // take into account max header (u2f usb) -static const uint8_t INFO[] = {1 /*info format 1*/, (char)(IO_APDU_BUFFER_SIZE - U2F_HANDLE_SIGN_HEADER_SIZE - 3 - 4), 0x90, 0x00}; - +static const uint8_t INFO[] = {1 /*info format 1*/, + (char) (IO_APDU_BUFFER_SIZE - U2F_HANDLE_SIGN_HEADER_SIZE - 3 - 4), + 0x90, + 0x00}; // proxy mode enroll issue an error -void u2f_apdu_enroll(u2f_service_t *service, uint8_t p1, uint8_t p2, - uint8_t *buffer, uint16_t length) { +void u2f_apdu_enroll(u2f_service_t *service, + uint8_t p1, + uint8_t p2, + uint8_t *buffer, + uint16_t length) +{ UNUSED(p1); UNUSED(p2); UNUSED(buffer); UNUSED(length); - u2f_message_reply(service, U2F_CMD_MSG, (uint8_t *)SW_INTERNAL, sizeof(SW_INTERNAL)); + u2f_message_reply(service, U2F_CMD_MSG, (uint8_t *) SW_INTERNAL, sizeof(SW_INTERNAL)); } -void u2f_apdu_sign(u2f_service_t *service, uint8_t p1, uint8_t p2, - uint8_t *buffer, uint16_t length) { +void u2f_apdu_sign(u2f_service_t *service, uint8_t p1, uint8_t p2, uint8_t *buffer, uint16_t length) +{ UNUSED(p2); uint8_t keyHandleLength; uint8_t i; // can't process the apdu if another one is already scheduled in if (G_io_app.apdu_state != APDU_IDLE) { - u2f_message_reply(service, U2F_CMD_MSG, - (uint8_t *)SW_BUSY, - sizeof(SW_BUSY)); + u2f_message_reply(service, U2F_CMD_MSG, (uint8_t *) SW_BUSY, sizeof(SW_BUSY)); return; } if (length < U2F_HANDLE_SIGN_HEADER_SIZE + 5 /*at least an apdu header*/) { - u2f_message_reply(service, U2F_CMD_MSG, - (uint8_t *)SW_WRONG_LENGTH, - sizeof(SW_WRONG_LENGTH)); + u2f_message_reply( + service, U2F_CMD_MSG, (uint8_t *) SW_WRONG_LENGTH, sizeof(SW_WRONG_LENGTH)); return; } // Confirm immediately if it's just a validation call if (p1 == P1_SIGN_CHECK_ONLY) { - u2f_message_reply(service, U2F_CMD_MSG, - (uint8_t *)SW_PROOF_OF_PRESENCE_REQUIRED, - sizeof(SW_PROOF_OF_PRESENCE_REQUIRED)); + u2f_message_reply(service, + U2F_CMD_MSG, + (uint8_t *) SW_PROOF_OF_PRESENCE_REQUIRED, + sizeof(SW_PROOF_OF_PRESENCE_REQUIRED)); return; } // Unwrap magic keyHandleLength = buffer[U2F_HANDLE_SIGN_HEADER_SIZE - 1]; if (U2F_HANDLE_SIGN_HEADER_SIZE + keyHandleLength != length) { - u2f_message_reply(service, U2F_CMD_MSG, - (uint8_t *)SW_WRONG_LENGTH, sizeof(SW_WRONG_LENGTH)); + u2f_message_reply( + service, U2F_CMD_MSG, (uint8_t *) SW_WRONG_LENGTH, sizeof(SW_WRONG_LENGTH)); return; } @@ -138,41 +142,42 @@ void u2f_apdu_sign(u2f_service_t *service, uint8_t p1, uint8_t p2, // this apdu is not subject to proxy magic masking // APDU is F1 D0 00 00 00 to get the magic proxy // RAPDU: <> - if (memcmp(buffer+U2F_HANDLE_SIGN_HEADER_SIZE, "\xF1\xD0\x00\x00\x00", 5) == 0 ) { + if (memcmp(buffer + U2F_HANDLE_SIGN_HEADER_SIZE, "\xF1\xD0\x00\x00\x00", 5) == 0) { // U2F_PROXY_MAGIC is given as a 0 terminated string - G_io_apdu_buffer[0] = sizeof(U2F_PROXY_MAGIC)-1; - memcpy(G_io_apdu_buffer+1, U2F_PROXY_MAGIC, sizeof(U2F_PROXY_MAGIC)-1); - memcpy(G_io_apdu_buffer+1+sizeof(U2F_PROXY_MAGIC)-1, "\x90\x00\x90\x00", 4); - u2f_message_reply(service, U2F_CMD_MSG, - (uint8_t *)G_io_apdu_buffer, - G_io_apdu_buffer[0]+1+2+2); + G_io_apdu_buffer[0] = sizeof(U2F_PROXY_MAGIC) - 1; + memcpy(G_io_apdu_buffer + 1, U2F_PROXY_MAGIC, sizeof(U2F_PROXY_MAGIC) - 1); + memcpy(G_io_apdu_buffer + 1 + sizeof(U2F_PROXY_MAGIC) - 1, "\x90\x00\x90\x00", 4); + u2f_message_reply(service, + U2F_CMD_MSG, + (uint8_t *) G_io_apdu_buffer, + G_io_apdu_buffer[0] + 1 + 2 + 2); // processing finished. don't go further in the u2f msg processing return; } } - for (i = 0; i < keyHandleLength; i++) { - buffer[U2F_HANDLE_SIGN_HEADER_SIZE + i] ^= U2F_PROXY_MAGIC[i % (sizeof(U2F_PROXY_MAGIC)-1)]; + buffer[U2F_HANDLE_SIGN_HEADER_SIZE + i] + ^= U2F_PROXY_MAGIC[i % (sizeof(U2F_PROXY_MAGIC) - 1)]; } // Check that it looks like an APDU if (length != U2F_HANDLE_SIGN_HEADER_SIZE + 5 + buffer[U2F_HANDLE_SIGN_HEADER_SIZE + 4]) { - u2f_message_reply(service, U2F_CMD_MSG, - (uint8_t *)SW_BAD_KEY_HANDLE, - sizeof(SW_BAD_KEY_HANDLE)); + u2f_message_reply( + service, U2F_CMD_MSG, (uint8_t *) SW_BAD_KEY_HANDLE, sizeof(SW_BAD_KEY_HANDLE)); return; } // make the apdu available to higher layers memmove(G_io_apdu_buffer, buffer + U2F_HANDLE_SIGN_HEADER_SIZE, keyHandleLength); G_io_app.apdu_length = keyHandleLength; - G_io_app.apdu_media = IO_APDU_MEDIA_U2F; // the effective transport is managed by the U2F layer + G_io_app.apdu_media = IO_APDU_MEDIA_U2F; // the effective transport is managed by the U2F layer G_io_app.apdu_state = APDU_U2F; // prepare for asynch reply u2f_message_set_autoreply_wait_user_presence(service, true); - // don't reset the u2f processing command state, as we still await for the io_exchange caller to make the response call + // don't reset the u2f processing command state, as we still await for the io_exchange caller to + // make the response call /* app_dispatch(); if ((btchip_context_D.io_flags & IO_ASYNCH_REPLY) == 0) { @@ -181,38 +186,50 @@ void u2f_apdu_sign(u2f_service_t *service, uint8_t p1, uint8_t p2, */ } -void u2f_apdu_get_version(u2f_service_t *service, uint8_t p1, uint8_t p2, - uint8_t *buffer, uint16_t length) { +void u2f_apdu_get_version(u2f_service_t *service, + uint8_t p1, + uint8_t p2, + uint8_t *buffer, + uint16_t length) +{ // screen_printf("U2F version\n"); UNUSED(p1); UNUSED(p2); UNUSED(buffer); UNUSED(length); - u2f_message_reply(service, U2F_CMD_MSG, (uint8_t *)U2F_VERSION, sizeof(U2F_VERSION)); + u2f_message_reply(service, U2F_CMD_MSG, (uint8_t *) U2F_VERSION, sizeof(U2F_VERSION)); } // Special command that returns the proxy -void u2f_apdu_get_info(u2f_service_t *service, uint8_t p1, uint8_t p2, - uint8_t *buffer, uint16_t length) { +void u2f_apdu_get_info(u2f_service_t *service, + uint8_t p1, + uint8_t p2, + uint8_t *buffer, + uint16_t length) +{ UNUSED(p1); UNUSED(p2); UNUSED(buffer); UNUSED(length); - u2f_message_reply(service, U2F_CMD_MSG, (uint8_t *)INFO, sizeof(INFO)); + u2f_message_reply(service, U2F_CMD_MSG, (uint8_t *) INFO, sizeof(INFO)); } -#endif // U2F_PROXY_MAGIC +#endif // U2F_PROXY_MAGIC -void u2f_handle_cmd_init(u2f_service_t *service, uint8_t *buffer, - uint16_t length, uint8_t *channelInit) { +void u2f_handle_cmd_init(u2f_service_t *service, + uint8_t *buffer, + uint16_t length, + uint8_t *channelInit) +{ // screen_printf("U2F init\n"); uint8_t channel[4]; - (void)length; + (void) length; if (u2f_is_channel_broadcast(channelInit)) { // cx_rng_no_throw(channel, 4); // not available within the IO task, just do without - service->next_channel += 1; + service->next_channel += 1; U4BE_ENCODE(channel, 0, service->next_channel); - } else { + } + else { memcpy(channel, channelInit, 4); } memmove(G_io_apdu_buffer, buffer, 8); @@ -225,19 +242,21 @@ void u2f_handle_cmd_init(u2f_service_t *service, uint8_t *buffer, if (u2f_is_channel_broadcast(channelInit)) { memset(service->channel, 0xff, 4); - } else { + } + else { memcpy(service->channel, channel, 4); } u2f_message_reply(service, U2F_CMD_INIT, G_io_apdu_buffer, 17); } -void u2f_handle_cmd_ping(u2f_service_t *service, uint8_t *buffer, - uint16_t length) { +void u2f_handle_cmd_ping(u2f_service_t *service, uint8_t *buffer, uint16_t length) +{ // screen_printf("U2F ping\n"); u2f_message_reply(service, U2F_CMD_PING, buffer, length); } -int u2f_get_cmd_msg_data_length(const uint8_t *buffer, uint16_t length) { +int u2f_get_cmd_msg_data_length(const uint8_t *buffer, uint16_t length) +{ /* Parse buffer to retrieve the data length. Only Extended encoding is supported */ @@ -290,35 +309,34 @@ int u2f_get_cmd_msg_data_length(const uint8_t *buffer, uint16_t length) { // Can't be short encoding as Lc = 0 would lead to invalid length // so extended encoding with Lc field present, optionally Le (2B) is present too - uint32_t dataLength = (buffer[LC_FIRST_BYTE_OFFSET + 1] << 8) | - (buffer[LC_FIRST_BYTE_OFFSET + 2]); + uint32_t dataLength + = (buffer[LC_FIRST_BYTE_OFFSET + 1] << 8) | (buffer[LC_FIRST_BYTE_OFFSET + 2]); // Ensure that Lc value is consistent - if ((APDU_MIN_HEADER + LONG_ENC_LC_SIZE + dataLength != length) && \ - (APDU_MIN_HEADER + LONG_ENC_LC_SIZE + dataLength + LONG_ENC_LE_SIZE != length)) { + if ((APDU_MIN_HEADER + LONG_ENC_LC_SIZE + dataLength != length) + && (APDU_MIN_HEADER + LONG_ENC_LC_SIZE + dataLength + LONG_ENC_LE_SIZE != length)) { return -1; } return dataLength; } -void u2f_handle_cmd_msg(u2f_service_t *service, uint8_t *buffer, - uint16_t length) { +void u2f_handle_cmd_msg(u2f_service_t *service, uint8_t *buffer, uint16_t length) +{ // screen_printf("U2F msg\n"); #ifdef U2F_PROXY_MAGIC uint8_t cla = buffer[OFFSET_CLA]; uint8_t ins = buffer[OFFSET_INS]; - uint8_t p1 = buffer[OFFSET_P1]; - uint8_t p2 = buffer[OFFSET_P2]; -#endif // U2F_PROXY_MAGIC + uint8_t p1 = buffer[OFFSET_P1]; + uint8_t p2 = buffer[OFFSET_P2]; +#endif // U2F_PROXY_MAGIC uint32_t dataLength = u2f_get_cmd_msg_data_length(buffer, length); if (dataLength < 0) { // invalid size - u2f_message_reply(service, U2F_CMD_MSG, - (uint8_t *)SW_WRONG_LENGTH, - sizeof(SW_WRONG_LENGTH)); + u2f_message_reply( + service, U2F_CMD_MSG, (uint8_t *) SW_WRONG_LENGTH, sizeof(SW_WRONG_LENGTH)); return; } @@ -327,67 +345,68 @@ void u2f_handle_cmd_msg(u2f_service_t *service, uint8_t *buffer, // No proxy mode, just pass the APDU as it is to the upper layer memmove(G_io_apdu_buffer, buffer, length); G_io_app.apdu_length = length; - G_io_app.apdu_media = IO_APDU_MEDIA_U2F; // the effective transport is managed by the U2F layer + G_io_app.apdu_media = IO_APDU_MEDIA_U2F; // the effective transport is managed by the U2F layer G_io_app.apdu_state = APDU_U2F; -#else // U2F_PROXY_MAGIC +#else // U2F_PROXY_MAGIC if (cla != FIDO_CLA) { - u2f_message_reply(service, U2F_CMD_MSG, - (uint8_t *)SW_UNKNOWN_CLASS, - sizeof(SW_UNKNOWN_CLASS)); + u2f_message_reply( + service, U2F_CMD_MSG, (uint8_t *) SW_UNKNOWN_CLASS, sizeof(SW_UNKNOWN_CLASS)); return; } switch (ins) { - case FIDO_INS_ENROLL: - // screen_printf("enroll\n"); - u2f_apdu_enroll(service, p1, p2, buffer + OFFSET_DATA, dataLength); - break; - case FIDO_INS_SIGN: - // screen_printf("sign\n"); - u2f_apdu_sign(service, p1, p2, buffer + OFFSET_DATA, dataLength); - break; - case FIDO_INS_GET_VERSION: - // screen_printf("version\n"); - u2f_apdu_get_version(service, p1, p2, buffer + OFFSET_DATA, dataLength); - break; - - // only support by - case FIDO_INS_PROP_GET_INFO: - u2f_apdu_get_info(service, p1, p2, buffer + OFFSET_DATA, dataLength); - break; - - default: - // screen_printf("unsupported\n"); - u2f_message_reply(service, U2F_CMD_MSG, - (uint8_t *)SW_UNKNOWN_INSTRUCTION, - sizeof(SW_UNKNOWN_INSTRUCTION)); - return; + case FIDO_INS_ENROLL: + // screen_printf("enroll\n"); + u2f_apdu_enroll(service, p1, p2, buffer + OFFSET_DATA, dataLength); + break; + case FIDO_INS_SIGN: + // screen_printf("sign\n"); + u2f_apdu_sign(service, p1, p2, buffer + OFFSET_DATA, dataLength); + break; + case FIDO_INS_GET_VERSION: + // screen_printf("version\n"); + u2f_apdu_get_version(service, p1, p2, buffer + OFFSET_DATA, dataLength); + break; + + // only support by + case FIDO_INS_PROP_GET_INFO: + u2f_apdu_get_info(service, p1, p2, buffer + OFFSET_DATA, dataLength); + break; + + default: + // screen_printf("unsupported\n"); + u2f_message_reply(service, + U2F_CMD_MSG, + (uint8_t *) SW_UNKNOWN_INSTRUCTION, + sizeof(SW_UNKNOWN_INSTRUCTION)); + return; } -#endif // U2F_PROXY_MAGIC +#endif // U2F_PROXY_MAGIC } -void u2f_message_complete(u2f_service_t *service) { - uint8_t cmd = service->transportBuffer[0]; +void u2f_message_complete(u2f_service_t *service) +{ + uint8_t cmd = service->transportBuffer[0]; uint16_t length = (service->transportBuffer[1] << 8) | (service->transportBuffer[2]); switch (cmd) { - case U2F_CMD_INIT: - u2f_handle_cmd_init(service, service->transportBuffer + 3, length, service->channel); - break; - case U2F_CMD_PING: - u2f_handle_cmd_ping(service, service->transportBuffer + 3, length); - break; - case U2F_CMD_MSG: - u2f_handle_cmd_msg(service, service->transportBuffer + 3, length); - break; + case U2F_CMD_INIT: + u2f_handle_cmd_init(service, service->transportBuffer + 3, length, service->channel); + break; + case U2F_CMD_PING: + u2f_handle_cmd_ping(service, service->transportBuffer + 3, length); + break; + case U2F_CMD_MSG: + u2f_handle_cmd_msg(service, service->transportBuffer + 3, length); + break; #ifdef HAVE_FIDO2 - case CTAP2_CMD_CBOR: - ctap2_handle_cmd_cbor(service, service->transportBuffer + 3, length); - break; - case CTAP2_CMD_CANCEL: - ctap2_handle_cmd_cancel(service, service->transportBuffer + 3, length); - break; + case CTAP2_CMD_CBOR: + ctap2_handle_cmd_cbor(service, service->transportBuffer + 3, length); + break; + case CTAP2_CMD_CANCEL: + ctap2_handle_cmd_cancel(service, service->transportBuffer + 3, length); + break; #endif } } diff --git a/lib_stusb_impl/u2f_impl.h b/lib_stusb_impl/u2f_impl.h index 90cbabc0e..aadf92b64 100644 --- a/lib_stusb_impl/u2f_impl.h +++ b/lib_stusb_impl/u2f_impl.h @@ -1,20 +1,20 @@ /******************************************************************************* -* Ledger Nano S - Secure firmware -* (c) 2022 Ledger -* -* Licensed under the Apache License, Version 2.0 (the "License"); -* you may not use this file except in compliance with the License. -* You may obtain a copy of the License at -* -* http://www.apache.org/licenses/LICENSE-2.0 -* -* Unless required by applicable law or agreed to in writing, software -* distributed under the License is distributed on an "AS IS" BASIS, -* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -* See the License for the specific language governing permissions and -* limitations under the License. -********************************************************************************/ + * Ledger Nano S - Secure firmware + * (c) 2022 Ledger + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT 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 "usbd_hid_impl.h" diff --git a/lib_stusb_impl/u2f_io.c b/lib_stusb_impl/u2f_io.c index 25c3a0d06..a621abbda 100644 --- a/lib_stusb_impl/u2f_io.c +++ b/lib_stusb_impl/u2f_io.c @@ -1,20 +1,20 @@ /******************************************************************************* -* Ledger Nano S - Secure firmware -* (c) 2022 Ledger -* -* Licensed under the Apache License, Version 2.0 (the "License"); -* you may not use this file except in compliance with the License. -* You may obtain a copy of the License at -* -* http://www.apache.org/licenses/LICENSE-2.0 -* -* Unless required by applicable law or agreed to in writing, software -* distributed under the License is distributed on an "AS IS" BASIS, -* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -* See the License for the specific language governing permissions and -* limitations under the License. -********************************************************************************/ + * Ledger Nano S - Secure firmware + * (c) 2022 Ledger + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT 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 @@ -33,27 +33,28 @@ #include "ledger_ble.h" #endif -void u2f_io_send(uint8_t *buffer, uint16_t length, u2f_transport_media_t media) { +void u2f_io_send(uint8_t *buffer, uint16_t length, u2f_transport_media_t media) +{ if (media == U2F_MEDIA_USB) { memmove(G_io_usb_ep_buffer, buffer, length); // wipe the remaining to avoid : // 1/ data leaks // 2/ invalid junk - memset(G_io_usb_ep_buffer+length, 0, sizeof(G_io_usb_ep_buffer)-length); + memset(G_io_usb_ep_buffer + length, 0, sizeof(G_io_usb_ep_buffer) - length); } switch (media) { - case U2F_MEDIA_USB: - io_usb_send_ep(U2F_EPIN_ADDR, G_io_usb_ep_buffer, USB_SEGMENT_SIZE, 0); - break; + case U2F_MEDIA_USB: + io_usb_send_ep(U2F_EPIN_ADDR, G_io_usb_ep_buffer, USB_SEGMENT_SIZE, 0); + break; #ifdef HAVE_BLE - case U2F_MEDIA_BLE: - LEDGER_BLE_send(buffer, length); - break; + case U2F_MEDIA_BLE: + LEDGER_BLE_send(buffer, length); + break; #endif - default: - PRINTF("Request to send on unsupported media %d\n", media); - break; + default: + PRINTF("Request to send on unsupported media %d\n", media); + break; } } -#endif // HAVE_IO_U2F +#endif // HAVE_IO_U2F diff --git a/lib_stusb_impl/usbd_ccid_impl.h b/lib_stusb_impl/usbd_ccid_impl.h index e2d2beaee..889aa639e 100644 --- a/lib_stusb_impl/usbd_ccid_impl.h +++ b/lib_stusb_impl/usbd_ccid_impl.h @@ -1,20 +1,20 @@ /******************************************************************************* -* Ledger Nano S - Secure firmware -* (c) 2022 Ledger -* -* Licensed under the Apache License, Version 2.0 (the "License"); -* you may not use this file except in compliance with the License. -* You may obtain a copy of the License at -* -* http://www.apache.org/licenses/LICENSE-2.0 -* -* Unless required by applicable law or agreed to in writing, software -* distributed under the License is distributed on an "AS IS" BASIS, -* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -* See the License for the specific language governing permissions and -* limitations under the License. -********************************************************************************/ + * Ledger Nano S - Secure firmware + * (c) 2022 Ledger + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT 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 USBD_CCID_IMPL_H #define USBD_CCID_IMPL_H @@ -24,27 +24,27 @@ // ================================================ // CCID -#define TPDU_EXCHANGE 0x01 -#define SHORT_APDU_EXCHANGE 0x02 -#define EXTENDED_APDU_EXCHANGE 0x04 -#define CHARACTER_EXCHANGE 0x00 +#define TPDU_EXCHANGE 0x01 +#define SHORT_APDU_EXCHANGE 0x02 +#define EXTENDED_APDU_EXCHANGE 0x04 +#define CHARACTER_EXCHANGE 0x00 -#define EXCHANGE_LEVEL_FEATURE SHORT_APDU_EXCHANGE +#define EXCHANGE_LEVEL_FEATURE SHORT_APDU_EXCHANGE -#define CCID_INTF 2 -#define CCID_BULK_IN_EP 0x83 -#define CCID_BULK_EPIN_SIZE 64 -#define CCID_BULK_OUT_EP 0x03 -#define CCID_BULK_EPOUT_SIZE 64 +#define CCID_INTF 2 +#define CCID_BULK_IN_EP 0x83 +#define CCID_BULK_EPIN_SIZE 64 +#define CCID_BULK_OUT_EP 0x03 +#define CCID_BULK_EPOUT_SIZE 64 #ifdef HAVE_CCID_INTERRUPT -#define CCID_INTR_IN_EP 0x84 -#define CCID_INTR_EPIN_SIZE 16 -#endif // HAVE_CCID_INTERRUPT +#define CCID_INTR_IN_EP 0x84 +#define CCID_INTR_EPIN_SIZE 16 +#endif // HAVE_CCID_INTERRUPT #define IO_CCID_DATA_BUFFER_SIZE IO_APDU_BUFFER_SIZE -#define G_io_ccid_data_buffer G_io_apdu_buffer +#define G_io_ccid_data_buffer G_io_apdu_buffer -#endif // HAVE_USB_CLASS_CCID +#endif // HAVE_USB_CLASS_CCID -#endif // USBD_CCID_IMPL_H +#endif // USBD_CCID_IMPL_H diff --git a/lib_stusb_impl/usbd_hid_impl.h b/lib_stusb_impl/usbd_hid_impl.h index 77f086d1b..877cb873a 100644 --- a/lib_stusb_impl/usbd_hid_impl.h +++ b/lib_stusb_impl/usbd_hid_impl.h @@ -1,20 +1,20 @@ /******************************************************************************* -* Ledger Nano S - Secure firmware -* (c) 2022 Ledger -* -* Licensed under the Apache License, Version 2.0 (the "License"); -* you may not use this file except in compliance with the License. -* You may obtain a copy of the License at -* -* http://www.apache.org/licenses/LICENSE-2.0 -* -* Unless required by applicable law or agreed to in writing, software -* distributed under the License is distributed on an "AS IS" BASIS, -* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -* See the License for the specific language governing permissions and -* limitations under the License. -********************************************************************************/ + * Ledger Nano S - Secure firmware + * (c) 2022 Ledger + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT 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 USBD_HID_IMPL_H #define USBD_HID_IMPL_H @@ -22,44 +22,43 @@ // ================================================ // HIDGEN -#define HID_INTF 0 +#define HID_INTF 0 -#define HID_EPIN_ADDR 0x82 -#define HID_EPIN_SIZE 0x40 - -#define HID_EPOUT_ADDR 0x02 -#define HID_EPOUT_SIZE 0x40 +#define HID_EPIN_ADDR 0x82 +#define HID_EPIN_SIZE 0x40 +#define HID_EPOUT_ADDR 0x02 +#define HID_EPOUT_SIZE 0x40 #ifdef HAVE_IO_U2F // ================================================ // HID U2F -#define U2F_INTF 1 +#define U2F_INTF 1 -#define U2F_EPIN_ADDR 0x81 -#define U2F_EPIN_SIZE 0x40 +#define U2F_EPIN_ADDR 0x81 +#define U2F_EPIN_SIZE 0x40 -#define U2F_EPOUT_ADDR 0x01 -#define U2F_EPOUT_SIZE 0x40 -#endif // HAVE_IO_U2F +#define U2F_EPOUT_ADDR 0x01 +#define U2F_EPOUT_SIZE 0x40 +#endif // HAVE_IO_U2F #ifdef HAVE_WEBUSB -#define WEBUSB_EPIN_ADDR 0x83 -#define WEBUSB_EPIN_SIZE 0x40 -#define WEBUSB_EPOUT_ADDR 0x03 -#define WEBUSB_EPOUT_SIZE 0x40 +#define WEBUSB_EPIN_ADDR 0x83 +#define WEBUSB_EPIN_SIZE 0x40 +#define WEBUSB_EPOUT_ADDR 0x03 +#define WEBUSB_EPOUT_SIZE 0x40 #ifdef HAVE_USB_CLASS_CCID - #error Unsupported CCID+WEBUSB, not enough endpoints -#endif // HAVE_USB_CLASS_CCID +#error Unsupported CCID+WEBUSB, not enough endpoints +#endif // HAVE_USB_CLASS_CCID #ifdef HAVE_IO_U2F #define WEBUSB_INTF 2 -#else // HAVE_IO_U2F +#else // HAVE_IO_U2F #define WEBUSB_INTF 1 -#endif // HAVE_IO_U2F -#endif // HAVE_WEBUSB +#endif // HAVE_IO_U2F +#endif // HAVE_WEBUSB -#endif // USBD_HID_IMPL_H +#endif // USBD_HID_IMPL_H diff --git a/lib_stusb_impl/usbd_impl.c b/lib_stusb_impl/usbd_impl.c index 899da02c4..72b286c45 100644 --- a/lib_stusb_impl/usbd_impl.c +++ b/lib_stusb_impl/usbd_impl.c @@ -1,49 +1,49 @@ /** - ****************************************************************************** - * @file usbd_hid.c - * @author MCD Application Team - * @version V2.2.0 - * @date 13-June-2014 - * @brief This file provides the HID core functions. - * - * @verbatim - * - * =================================================================== - * HID Class Description - * =================================================================== - * This module manages the HID class V1.11 following the "Device Class Definition - * for Human Interface Devices (HID) Version 1.11 Jun 27, 2001". - * This driver implements the following aspects of the specification: - * - The Boot Interface Subclass - * - Usage Page : Generic Desktop - * - Usage : Vendor - * - Collection : Application - * - * @note In HS mode and when the DMA is used, all variables and data structures - * dealing with the DMA during the transaction process should be 32-bit aligned. - * - * - * @endverbatim - * - ****************************************************************************** - * @attention - * - *

© COPYRIGHT 2014 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. - * - ****************************************************************************** - */ + ****************************************************************************** + * @file usbd_hid.c + * @author MCD Application Team + * @version V2.2.0 + * @date 13-June-2014 + * @brief This file provides the HID core functions. + * + * @verbatim + * + * =================================================================== + * HID Class Description + * =================================================================== + * This module manages the HID class V1.11 following the "Device Class Definition + * for Human Interface Devices (HID) Version 1.11 Jun 27, 2001". + * This driver implements the following aspects of the specification: + * - The Boot Interface Subclass + * - Usage Page : Generic Desktop + * - Usage : Vendor + * - Collection : Application + * + * @note In HS mode and when the DMA is used, all variables and data structures + * dealing with the DMA during the transaction process should be 32-bit aligned. + * + * + * @endverbatim + * + ****************************************************************************** + * @attention + * + *

© COPYRIGHT 2014 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. + * + ****************************************************************************** + */ #include "os.h" #include "os_io_usb.h" @@ -67,61 +67,57 @@ #ifdef HAVE_IO_U2F #include "u2f_transport.h" #include "u2f_impl.h" -#endif // HAVE_IO_U2F +#endif // HAVE_IO_U2F #ifdef HAVE_USB_CLASS_CCID #include "usbd_ccid_core.h" -#endif // HAVE_USB_CLASS_CCID - +#endif // HAVE_USB_CLASS_CCID /** @addtogroup STM32_USB_DEVICE_LIBRARY - * @{ - */ - + * @{ + */ /** @defgroup USBD_HID - * @brief usbd core module - * @{ - */ + * @brief usbd core module + * @{ + */ /** @defgroup USBD_HID_Private_TypesDefinitions - * @{ - */ + * @{ + */ /** - * @} - */ - + * @} + */ /** @defgroup USBD_HID_Private_Defines - * @{ - */ + * @{ + */ /** - * @} - */ - + * @} + */ /** @defgroup USBD_HID_Private_Macros - * @{ - */ + * @{ + */ /** - * @} - */ + * @} + */ /** @defgroup USBD_HID_Private_FunctionPrototypes - * @{ - */ - + * @{ + */ /** - * @} - */ + * @} + */ /** @defgroup USBD_HID_Private_Variables - * @{ - */ + * @{ + */ -#define USBD_LANGID_STRING 0x409 +#define USBD_LANGID_STRING 0x409 +// clang-format off #ifdef HAVE_VID_PID_PROBER #define USBD_VID 0x2581 #define USBD_PID 0xf1d1 @@ -760,393 +756,380 @@ static uint8_t const USBD_DeviceDesc[]= { USBD_IDX_SERIAL_STR, /* Index of serial number string */ 1 /* bNumConfigurations */ }; /* USB_DeviceDescriptor */ - +// clang-format on /** - * @brief Returns the device descriptor. - * @param speed: Current device speed - * @param length: Pointer to data length variable - * @retval Pointer to descriptor buffer - */ + * @brief Returns the device descriptor. + * @param speed: Current device speed + * @param length: Pointer to data length variable + * @retval Pointer to descriptor buffer + */ static uint8_t *USBD_DeviceDescriptor(USBD_SpeedTypeDef speed, uint16_t *length) { - UNUSED(speed); - *length = sizeof(USBD_DeviceDesc); - return (uint8_t*)USBD_DeviceDesc; + UNUSED(speed); + *length = sizeof(USBD_DeviceDesc); + return (uint8_t *) USBD_DeviceDesc; } /** - * @brief Returns the LangID string descriptor. - * @param speed: Current device speed - * @param length: Pointer to data length variable - * @retval Pointer to descriptor buffer - */ + * @brief Returns the LangID string descriptor. + * @param speed: Current device speed + * @param length: Pointer to data length variable + * @retval Pointer to descriptor buffer + */ static uint8_t *USBD_LangIDStrDescriptor(USBD_SpeedTypeDef speed, uint16_t *length) { - UNUSED(speed); - *length = sizeof(USBD_LangIDDesc); - return (uint8_t*)USBD_LangIDDesc; + UNUSED(speed); + *length = sizeof(USBD_LangIDDesc); + return (uint8_t *) USBD_LangIDDesc; } /** - * @brief Returns the product string descriptor. - * @param speed: Current device speed - * @param length: Pointer to data length variable - * @retval Pointer to descriptor buffer - */ + * @brief Returns the product string descriptor. + * @param speed: Current device speed + * @param length: Pointer to data length variable + * @retval Pointer to descriptor buffer + */ static uint8_t *USBD_ProductStrDescriptor(USBD_SpeedTypeDef speed, uint16_t *length) { - UNUSED(speed); - *length = sizeof(USBD_PRODUCT_FS_STRING); - return (uint8_t*)USBD_PRODUCT_FS_STRING; + UNUSED(speed); + *length = sizeof(USBD_PRODUCT_FS_STRING); + return (uint8_t *) USBD_PRODUCT_FS_STRING; } /** - * @brief Returns the manufacturer string descriptor. - * @param speed: Current device speed - * @param length: Pointer to data length variable - * @retval Pointer to descriptor buffer - */ + * @brief Returns the manufacturer string descriptor. + * @param speed: Current device speed + * @param length: Pointer to data length variable + * @retval Pointer to descriptor buffer + */ static uint8_t *USBD_ManufacturerStrDescriptor(USBD_SpeedTypeDef speed, uint16_t *length) { - UNUSED(speed); - *length = sizeof(USBD_MANUFACTURER_STRING); - return (uint8_t*)USBD_MANUFACTURER_STRING; + UNUSED(speed); + *length = sizeof(USBD_MANUFACTURER_STRING); + return (uint8_t *) USBD_MANUFACTURER_STRING; } /** - * @brief Returns the serial number string descriptor. - * @param speed: Current device speed - * @param length: Pointer to data length variable - * @retval Pointer to descriptor buffer - */ + * @brief Returns the serial number string descriptor. + * @param speed: Current device speed + * @param length: Pointer to data length variable + * @retval Pointer to descriptor buffer + */ static uint8_t *USBD_SerialStrDescriptor(USBD_SpeedTypeDef speed, uint16_t *length) { - UNUSED(speed); - *length = sizeof(USB_SERIAL_STRING); - return (uint8_t*)USB_SERIAL_STRING; + UNUSED(speed); + *length = sizeof(USB_SERIAL_STRING); + return (uint8_t *) USB_SERIAL_STRING; } /** - * @brief Returns the configuration string descriptor. - * @param speed: Current device speed - * @param length: Pointer to data length variable - * @retval Pointer to descriptor buffer - */ + * @brief Returns the configuration string descriptor. + * @param speed: Current device speed + * @param length: Pointer to data length variable + * @retval Pointer to descriptor buffer + */ static uint8_t *USBD_ConfigStrDescriptor(USBD_SpeedTypeDef speed, uint16_t *length) { - UNUSED(speed); - *length = sizeof(USBD_CONFIGURATION_FS_STRING); - return (uint8_t*)USBD_CONFIGURATION_FS_STRING; + UNUSED(speed); + *length = sizeof(USBD_CONFIGURATION_FS_STRING); + return (uint8_t *) USBD_CONFIGURATION_FS_STRING; } /** - * @brief Returns the interface string descriptor. - * @param speed: Current device speed - * @param length: Pointer to data length variable - * @retval Pointer to descriptor buffer - */ + * @brief Returns the interface string descriptor. + * @param speed: Current device speed + * @param length: Pointer to data length variable + * @retval Pointer to descriptor buffer + */ static uint8_t *USBD_InterfaceStrDescriptor(USBD_SpeedTypeDef speed, uint16_t *length) { - UNUSED(speed); - *length = sizeof(USBD_INTERFACE_FS_STRING); - return (uint8_t*)USBD_INTERFACE_FS_STRING; + UNUSED(speed); + *length = sizeof(USBD_INTERFACE_FS_STRING); + return (uint8_t *) USBD_INTERFACE_FS_STRING; } /** -* @brief DeviceQualifierDescriptor -* return Device Qualifier descriptor -* @param length : pointer data length -* @retval pointer to descriptor buffer -*/ -static uint8_t *USBD_GetDeviceQualifierDesc_impl (uint16_t *length) + * @brief DeviceQualifierDescriptor + * return Device Qualifier descriptor + * @param length : pointer data length + * @retval pointer to descriptor buffer + */ +static uint8_t *USBD_GetDeviceQualifierDesc_impl(uint16_t *length) { - *length = sizeof (USBD_DeviceQualifierDesc); - return (uint8_t*)USBD_DeviceQualifierDesc; + *length = sizeof(USBD_DeviceQualifierDesc); + return (uint8_t *) USBD_DeviceQualifierDesc; } /** - * @brief USBD_CUSTOM_HID_GetCfgDesc - * return configuration descriptor - * @param speed : current device speed - * @param length : pointer data length - * @retval pointer to descriptor buffer - */ -static uint8_t *USBD_GetCfgDesc_impl (uint16_t *length) + * @brief USBD_CUSTOM_HID_GetCfgDesc + * return configuration descriptor + * @param speed : current device speed + * @param length : pointer data length + * @retval pointer to descriptor buffer + */ +static uint8_t *USBD_GetCfgDesc_impl(uint16_t *length) { - *length = sizeof (USBD_CfgDesc); - return (uint8_t*)USBD_CfgDesc; + *length = sizeof(USBD_CfgDesc); + return (uint8_t *) USBD_CfgDesc; } -uint8_t* USBD_HID_GetHidDescriptor_impl(uint16_t* len) { - switch (USBD_Device.request.wIndex&0xFF) { +uint8_t *USBD_HID_GetHidDescriptor_impl(uint16_t *len) +{ + switch (USBD_Device.request.wIndex & 0xFF) { #ifdef HAVE_IO_U2F - case U2F_INTF: - *len = sizeof(USBD_HID_Desc_fido); - return (uint8_t*)USBD_HID_Desc_fido; -#endif // HAVE_IO_U2F + case U2F_INTF: + *len = sizeof(USBD_HID_Desc_fido); + return (uint8_t *) USBD_HID_Desc_fido; +#endif // HAVE_IO_U2F #ifndef HAVE_USB_HIDKBD - case HID_INTF: - *len = sizeof(USBD_HID_Desc); - return (uint8_t*)USBD_HID_Desc; + case HID_INTF: + *len = sizeof(USBD_HID_Desc); + return (uint8_t *) USBD_HID_Desc; #else - case HID_INTF: - *len = sizeof(USBD_HID_Desc_kbd); - return (uint8_t*)USBD_HID_Desc_kbd; -#endif // HAVE_USB_HIDKBD - } - *len = 0; - return 0; + case HID_INTF: + *len = sizeof(USBD_HID_Desc_kbd); + return (uint8_t *) USBD_HID_Desc_kbd; +#endif // HAVE_USB_HIDKBD + } + *len = 0; + return 0; } -uint8_t* USBD_HID_GetReportDescriptor_impl(uint16_t* len) { - switch (USBD_Device.request.wIndex&0xFF) { +uint8_t *USBD_HID_GetReportDescriptor_impl(uint16_t *len) +{ + switch (USBD_Device.request.wIndex & 0xFF) { #ifdef HAVE_IO_U2F - case U2F_INTF: - - // very dirty work due to lack of callback when USB_HID_Init is called - USBD_LL_OpenEP(&USBD_Device, - U2F_EPIN_ADDR, - USBD_EP_TYPE_INTR, - U2F_EPIN_SIZE); + case U2F_INTF: - USBD_LL_OpenEP(&USBD_Device, - U2F_EPOUT_ADDR, - USBD_EP_TYPE_INTR, - U2F_EPOUT_SIZE); + // very dirty work due to lack of callback when USB_HID_Init is called + USBD_LL_OpenEP(&USBD_Device, U2F_EPIN_ADDR, USBD_EP_TYPE_INTR, U2F_EPIN_SIZE); - /* Prepare Out endpoint to receive 1st packet */ - USBD_LL_PrepareReceive(&USBD_Device, U2F_EPOUT_ADDR, U2F_EPOUT_SIZE); + USBD_LL_OpenEP(&USBD_Device, U2F_EPOUT_ADDR, USBD_EP_TYPE_INTR, U2F_EPOUT_SIZE); + /* Prepare Out endpoint to receive 1st packet */ + USBD_LL_PrepareReceive(&USBD_Device, U2F_EPOUT_ADDR, U2F_EPOUT_SIZE); - *len = sizeof(HID_ReportDesc_fido); - return (uint8_t*)HID_ReportDesc_fido; -#endif // HAVE_IO_U2F + *len = sizeof(HID_ReportDesc_fido); + return (uint8_t *) HID_ReportDesc_fido; +#endif // HAVE_IO_U2F #ifndef HAVE_USB_HIDKBD - case HID_INTF: - *len = sizeof(HID_ReportDesc); - return (uint8_t*)HID_ReportDesc; + case HID_INTF: + *len = sizeof(HID_ReportDesc); + return (uint8_t *) HID_ReportDesc; #else - case HID_INTF: - *len = sizeof(HID_ReportDesc_kbd); - return (uint8_t*)HID_ReportDesc_kbd; -#endif // HAVE_USB_HIDKBD - } - *len = 0; - return 0; + case HID_INTF: + *len = sizeof(HID_ReportDesc_kbd); + return (uint8_t *) HID_ReportDesc_kbd; +#endif // HAVE_USB_HIDKBD + } + *len = 0; + return 0; } /** - * @} - */ - + * @} + */ /** - * @brief USBD_HID_DataOut - * handle data OUT Stage - * @param pdev: device instance - * @param epnum: endpoint index - * @retval status - * - * This function is the default behavior for our implementation when data are sent over the out hid endpoint - */ + * @brief USBD_HID_DataOut + * handle data OUT Stage + * @param pdev: device instance + * @param epnum: endpoint index + * @retval status + * + * This function is the default behavior for our implementation when data are sent over the out hid + * endpoint + */ #ifdef HAVE_IO_U2F /** - * @brief USBD_HID_Init - * Initialize the HID interface - * @param pdev: device instance - * @param cfgidx: Configuration index - * @retval status - */ -uint8_t USBD_U2F_Init (USBD_HandleTypeDef *pdev, - uint8_t cfgidx) + * @brief USBD_HID_Init + * Initialize the HID interface + * @param pdev: device instance + * @param cfgidx: Configuration index + * @retval status + */ +uint8_t USBD_U2F_Init(USBD_HandleTypeDef *pdev, uint8_t cfgidx) { - UNUSED(cfgidx); + UNUSED(cfgidx); - /* Open EP IN */ - USBD_LL_OpenEP(pdev, - U2F_EPIN_ADDR, - USBD_EP_TYPE_INTR, - U2F_EPIN_SIZE); + /* Open EP IN */ + USBD_LL_OpenEP(pdev, U2F_EPIN_ADDR, USBD_EP_TYPE_INTR, U2F_EPIN_SIZE); - /* Open EP OUT */ - USBD_LL_OpenEP(pdev, - U2F_EPOUT_ADDR, - USBD_EP_TYPE_INTR, - U2F_EPOUT_SIZE); + /* Open EP OUT */ + USBD_LL_OpenEP(pdev, U2F_EPOUT_ADDR, USBD_EP_TYPE_INTR, U2F_EPOUT_SIZE); - /* Prepare Out endpoint to receive 1st packet */ - USBD_LL_PrepareReceive(pdev, U2F_EPOUT_ADDR, U2F_EPOUT_SIZE); + /* Prepare Out endpoint to receive 1st packet */ + USBD_LL_PrepareReceive(pdev, U2F_EPOUT_ADDR, U2F_EPOUT_SIZE); - return USBD_OK; + return USBD_OK; } -uint8_t USBD_U2F_DataIn_impl (USBD_HandleTypeDef *pdev, - uint8_t epnum) +uint8_t USBD_U2F_DataIn_impl(USBD_HandleTypeDef *pdev, uint8_t epnum) { - UNUSED(pdev); - // only the data hid endpoint will receive data - switch (epnum) { - // FIDO endpoint - case (U2F_EPIN_ADDR&0x7F): - // advance the u2f sending machine state - u2f_transport_sent(&G_io_u2f, U2F_MEDIA_USB); - break; - } - return USBD_OK; + UNUSED(pdev); + // only the data hid endpoint will receive data + switch (epnum) { + // FIDO endpoint + case (U2F_EPIN_ADDR & 0x7F): + // advance the u2f sending machine state + u2f_transport_sent(&G_io_u2f, U2F_MEDIA_USB); + break; + } + return USBD_OK; } -uint8_t USBD_U2F_DataOut_impl (USBD_HandleTypeDef *pdev, - uint8_t epnum, uint8_t* buffer, - __attribute__((unused)) apdu_buffer_t * apdu_buf) +uint8_t USBD_U2F_DataOut_impl(USBD_HandleTypeDef *pdev, + uint8_t epnum, + uint8_t *buffer, + __attribute__((unused)) apdu_buffer_t *apdu_buf) { - #ifdef HAVE_LOCAL_APDU_BUFFER - #error "Feature not implemented" +#error "Feature not implemented" #endif - switch (epnum) { - // FIDO endpoint - case (U2F_EPOUT_ADDR&0x7F): - USBD_LL_PrepareReceive(pdev, U2F_EPOUT_ADDR , U2F_EPOUT_SIZE); - u2f_transport_received(&G_io_u2f, buffer, io_seproxyhal_get_ep_rx_size(U2F_EPOUT_ADDR), U2F_MEDIA_USB); - break; - } + switch (epnum) { + // FIDO endpoint + case (U2F_EPOUT_ADDR & 0x7F): + USBD_LL_PrepareReceive(pdev, U2F_EPOUT_ADDR, U2F_EPOUT_SIZE); + u2f_transport_received( + &G_io_u2f, buffer, io_seproxyhal_get_ep_rx_size(U2F_EPOUT_ADDR), U2F_MEDIA_USB); + break; + } - return USBD_OK; + return USBD_OK; } -#endif // HAVE_IO_U2F +#endif // HAVE_IO_U2F -uint8_t USBD_HID_DataIn_impl (USBD_HandleTypeDef *pdev, - uint8_t epnum) +uint8_t USBD_HID_DataIn_impl(USBD_HandleTypeDef *pdev, uint8_t epnum) { - UNUSED(pdev); - switch (epnum) { - // HID gen endpoint - case (HID_EPIN_ADDR&0x7F): - io_usb_hid_sent(io_usb_send_apdu_data); - break; - } - - return USBD_OK; + UNUSED(pdev); + switch (epnum) { + // HID gen endpoint + case (HID_EPIN_ADDR & 0x7F): + io_usb_hid_sent(io_usb_send_apdu_data); + break; + } + + return USBD_OK; } -uint8_t USBD_HID_DataOut_impl (USBD_HandleTypeDef *pdev, uint8_t epnum, uint8_t* buffer, apdu_buffer_t * apdu_buf) +uint8_t USBD_HID_DataOut_impl(USBD_HandleTypeDef *pdev, + uint8_t epnum, + uint8_t *buffer, + apdu_buffer_t *apdu_buf) { - // only the data hid endpoint will receive data - switch (epnum) { - - // HID gen endpoint - case (HID_EPOUT_ADDR&0x7F): - // prepare receiving the next chunk (masked time) - USBD_LL_PrepareReceive(pdev, HID_EPOUT_ADDR , HID_EPOUT_SIZE); + // only the data hid endpoint will receive data + switch (epnum) { + // HID gen endpoint + case (HID_EPOUT_ADDR & 0x7F): + // prepare receiving the next chunk (masked time) + USBD_LL_PrepareReceive(pdev, HID_EPOUT_ADDR, HID_EPOUT_SIZE); #ifndef HAVE_USB_HIDKBD - // avoid troubles when an apdu has not been replied yet - if (G_io_app.apdu_media == IO_APDU_MEDIA_NONE) { - // add to the hid transport - switch(io_usb_hid_receive(io_usb_send_apdu_data, buffer, io_seproxyhal_get_ep_rx_size(HID_EPOUT_ADDR), apdu_buf)) { - default: - break; - - case IO_USB_APDU_RECEIVED: - G_io_app.apdu_media = IO_APDU_MEDIA_USB_HID; // for application code - G_io_app.apdu_state = APDU_USB_HID; // for next call to io_exchange - G_io_app.apdu_length = G_io_usb_hid_total_length; - break; - } + // avoid troubles when an apdu has not been replied yet + if (G_io_app.apdu_media == IO_APDU_MEDIA_NONE) { + // add to the hid transport + switch (io_usb_hid_receive(io_usb_send_apdu_data, + buffer, + io_seproxyhal_get_ep_rx_size(HID_EPOUT_ADDR), + apdu_buf)) { + default: + break; + + case IO_USB_APDU_RECEIVED: + G_io_app.apdu_media = IO_APDU_MEDIA_USB_HID; // for application code + G_io_app.apdu_state = APDU_USB_HID; // for next call to io_exchange + G_io_app.apdu_length = G_io_usb_hid_total_length; + break; + } + } +#endif // HAVE_USB_HIDKBD + break; } -#endif // HAVE_USB_HIDKBD - break; - } - return USBD_OK; + return USBD_OK; } #ifdef HAVE_WEBUSB -uint8_t USBD_WEBUSB_Init (USBD_HandleTypeDef *pdev, - uint8_t cfgidx) +uint8_t USBD_WEBUSB_Init(USBD_HandleTypeDef *pdev, uint8_t cfgidx) { - UNUSED(cfgidx); + UNUSED(cfgidx); - /* Open EP IN */ - USBD_LL_OpenEP(pdev, - WEBUSB_EPIN_ADDR, - USBD_EP_TYPE_INTR, - WEBUSB_EPIN_SIZE); + /* Open EP IN */ + USBD_LL_OpenEP(pdev, WEBUSB_EPIN_ADDR, USBD_EP_TYPE_INTR, WEBUSB_EPIN_SIZE); - /* Open EP OUT */ - USBD_LL_OpenEP(pdev, - WEBUSB_EPOUT_ADDR, - USBD_EP_TYPE_INTR, - WEBUSB_EPOUT_SIZE); + /* Open EP OUT */ + USBD_LL_OpenEP(pdev, WEBUSB_EPOUT_ADDR, USBD_EP_TYPE_INTR, WEBUSB_EPOUT_SIZE); - /* Prepare Out endpoint to receive 1st packet */ - USBD_LL_PrepareReceive(pdev, WEBUSB_EPOUT_ADDR, WEBUSB_EPOUT_SIZE); + /* Prepare Out endpoint to receive 1st packet */ + USBD_LL_PrepareReceive(pdev, WEBUSB_EPOUT_ADDR, WEBUSB_EPOUT_SIZE); - return USBD_OK; + return USBD_OK; } -uint8_t USBD_WEBUSB_DeInit (USBD_HandleTypeDef *pdev, - uint8_t cfgidx) { - UNUSED(pdev); - UNUSED(cfgidx); - return USBD_OK; +uint8_t USBD_WEBUSB_DeInit(USBD_HandleTypeDef *pdev, uint8_t cfgidx) +{ + UNUSED(pdev); + UNUSED(cfgidx); + return USBD_OK; } -uint8_t USBD_WEBUSB_Setup (USBD_HandleTypeDef *pdev, - USBD_SetupReqTypedef *req) +uint8_t USBD_WEBUSB_Setup(USBD_HandleTypeDef *pdev, USBD_SetupReqTypedef *req) { - UNUSED(pdev); - UNUSED(req); - return USBD_OK; + UNUSED(pdev); + UNUSED(req); + return USBD_OK; } -uint8_t USBD_WEBUSB_DataIn (USBD_HandleTypeDef *pdev, - uint8_t epnum) +uint8_t USBD_WEBUSB_DataIn(USBD_HandleTypeDef *pdev, uint8_t epnum) { - UNUSED(pdev); - switch (epnum) { - // HID gen endpoint - case (WEBUSB_EPIN_ADDR&0x7F): - io_usb_hid_sent(io_usb_send_apdu_data_ep0x83); - break; - } - return USBD_OK; + UNUSED(pdev); + switch (epnum) { + // HID gen endpoint + case (WEBUSB_EPIN_ADDR & 0x7F): + io_usb_hid_sent(io_usb_send_apdu_data_ep0x83); + break; + } + return USBD_OK; } -uint8_t USBD_WEBUSB_DataOut (USBD_HandleTypeDef *pdev, - uint8_t epnum, uint8_t* buffer, apdu_buffer_t* apdu_buf) +uint8_t USBD_WEBUSB_DataOut(USBD_HandleTypeDef *pdev, + uint8_t epnum, + uint8_t *buffer, + apdu_buffer_t *apdu_buf) { - // only the data hid endpoint will receive data - switch (epnum) { - - // HID gen endpoint - case (WEBUSB_EPOUT_ADDR&0x7F): - // prepare receiving the next chunk (masked time) - USBD_LL_PrepareReceive(pdev, WEBUSB_EPOUT_ADDR, WEBUSB_EPOUT_SIZE); - - // avoid troubles when an apdu has not been replied yet - if (G_io_app.apdu_media == IO_APDU_MEDIA_NONE) { - // add to the hid transport - switch(io_usb_hid_receive(io_usb_send_apdu_data_ep0x83, buffer, io_seproxyhal_get_ep_rx_size(WEBUSB_EPOUT_ADDR), apdu_buf)) { - default: - break; - - case IO_USB_APDU_RECEIVED: - G_io_app.apdu_media = IO_APDU_MEDIA_USB_WEBUSB; // for application code - G_io_app.apdu_state = APDU_USB_WEBUSB; // for next call to io_exchange - G_io_app.apdu_length = G_io_usb_hid_total_length; - break; - } + // only the data hid endpoint will receive data + switch (epnum) { + // HID gen endpoint + case (WEBUSB_EPOUT_ADDR & 0x7F): + // prepare receiving the next chunk (masked time) + USBD_LL_PrepareReceive(pdev, WEBUSB_EPOUT_ADDR, WEBUSB_EPOUT_SIZE); + + // avoid troubles when an apdu has not been replied yet + if (G_io_app.apdu_media == IO_APDU_MEDIA_NONE) { + // add to the hid transport + switch (io_usb_hid_receive(io_usb_send_apdu_data_ep0x83, + buffer, + io_seproxyhal_get_ep_rx_size(WEBUSB_EPOUT_ADDR), + apdu_buf)) { + default: + break; + + case IO_USB_APDU_RECEIVED: + G_io_app.apdu_media = IO_APDU_MEDIA_USB_WEBUSB; // for application code + G_io_app.apdu_state = APDU_USB_WEBUSB; // for next call to io_exchange + G_io_app.apdu_length = G_io_usb_hid_total_length; + break; + } + } + break; } - break; - } - return USBD_OK; + return USBD_OK; } // arbitrary vendor chosen @@ -1155,43 +1138,44 @@ uint8_t USBD_WEBUSB_DataOut (USBD_HandleTypeDef *pdev, // from https://wicg.github.io/webusb/#webusb-platform-capability-descriptor // see also this (for endianness explanation) // https://github.com/WICG/webusb/issues/115#issuecomment-352206549 -#define WEBUSB_UUID 0x38, 0xB6, 0x08, 0x34, 0xA9, 0x09, 0xA0, 0x47,0x8B, 0xFD, 0xA0, 0x76, 0x88, 0x15, 0xB6, 0x65 +#define WEBUSB_UUID \ + 0x38, 0xB6, 0x08, 0x34, 0xA9, 0x09, 0xA0, 0x47, 0x8B, 0xFD, 0xA0, 0x76, 0x88, 0x15, 0xB6, 0x65 -#define WEBUSB_REQ_GET_URL 0x02 +#define WEBUSB_REQ_GET_URL 0x02 -#define WEBUSB_DT_DESCRIPTOR_SET_HEADER 0 +#define WEBUSB_DT_DESCRIPTOR_SET_HEADER 0 #define WEBUSB_DT_CONFIGURATION_SUBSET_HEADER 1 -#define WEBUSB_DT_FUNCTION_SUBSET_HEADER 2 -#define WEBUSB_DT_URL 3 +#define WEBUSB_DT_FUNCTION_SUBSET_HEADER 2 +#define WEBUSB_DT_URL 3 -#define WEBUSB_URL_SCHEME_HTTP 0 -#define WEBUSB_URL_SCHEME_HTTPS 1 +#define WEBUSB_URL_SCHEME_HTTP 0 +#define WEBUSB_URL_SCHEME_HTTPS 1 #define WEBUSB_URL_SCHEME_CUSTOM 255 unsigned char const C_webusb_url_descriptor[] = { - // bLength - 3 + WEBUSB_URL_SIZE_B, - // bDescriptorType - WEBUSB_DT_URL, - // bScheme - WEBUSB_URL_SCHEME_HTTPS, - // URL - WEBUSB_URL -}; + // bLength + 3 + WEBUSB_URL_SIZE_B, + // bDescriptorType + WEBUSB_DT_URL, + // bScheme + WEBUSB_URL_SCHEME_HTTPS, + // URL + WEBUSB_URL}; /* USB 3.1 Descriptor Types - Table 9-6 */ -#define USB_DT_BOS 15 -#define USB_DT_DEVICE_CAPABILITY 16 +#define USB_DT_BOS 15 +#define USB_DT_DEVICE_CAPABILITY 16 #define USB_DT_BOS_SIZE 5 /* USB Device Capability Types - USB 3.1 Table 9-14 */ -#define USB_DC_PLATFORM 5 +#define USB_DC_PLATFORM 5 #define MS_OS_20_DESCRIPTOR_LENGTH (0xb2) #define WINUSB_VENDOR_CODE 0x77 +// clang-format off unsigned char const C_usb_bos[] = { USB_DT_BOS_SIZE, // bLength (5) USB_DT_BOS, // bDescriptorType @@ -1231,77 +1215,79 @@ unsigned char const C_usb_bos[] = { WINUSB_VENDOR_CODE, // Vendor-assigned bMS_VendorCode 0x00 // Doesn’t support alternate enumeration }; +// clang-format on -#endif // HAVE_WEBUSB +#endif // HAVE_WEBUSB static uint8_t *USBD_BOSDescriptor(USBD_SpeedTypeDef speed, uint16_t *length) { - UNUSED(speed); + UNUSED(speed); #ifdef HAVE_WEBUSB - *length = sizeof(C_usb_bos); - return (uint8_t*)C_usb_bos; + *length = sizeof(C_usb_bos); + return (uint8_t *) C_usb_bos; #else - *length = 0; - return NULL; + *length = 0; + return NULL; #endif } /** @defgroup USBD_HID_Private_Functions - * @{ - */ + * @{ + */ // note: how core lib usb calls the hid class USBD_DescriptorsTypeDef const HID_Desc = { - USBD_DeviceDescriptor, - USBD_LangIDStrDescriptor, - USBD_ManufacturerStrDescriptor, - USBD_ProductStrDescriptor, - USBD_SerialStrDescriptor, - USBD_ConfigStrDescriptor, - USBD_InterfaceStrDescriptor, - USBD_BOSDescriptor, + USBD_DeviceDescriptor, + USBD_LangIDStrDescriptor, + USBD_ManufacturerStrDescriptor, + USBD_ProductStrDescriptor, + USBD_SerialStrDescriptor, + USBD_ConfigStrDescriptor, + USBD_InterfaceStrDescriptor, + USBD_BOSDescriptor, }; #ifdef HAVE_IO_U2F -static USBD_ClassTypeDef const USBD_U2F = -{ - USBD_U2F_Init, - USBD_HID_DeInit, - USBD_HID_Setup, - NULL, /*EP0_TxSent*/ - NULL, /*EP0_RxReady*/ /* STATUS STAGE IN */ - USBD_U2F_DataIn_impl, /*DataIn*/ - USBD_U2F_DataOut_impl, /*DataOut*/ - NULL, /*SOF */ - NULL, - NULL, - USBD_GetCfgDesc_impl, - USBD_GetCfgDesc_impl, - USBD_GetCfgDesc_impl, - USBD_GetDeviceQualifierDesc_impl, +static USBD_ClassTypeDef const USBD_U2F = { + USBD_U2F_Init, + USBD_HID_DeInit, + USBD_HID_Setup, + NULL, /*EP0_TxSent*/ + NULL, + /*EP0_RxReady*/ /* STATUS STAGE IN */ + USBD_U2F_DataIn_impl, /*DataIn*/ + USBD_U2F_DataOut_impl, /*DataOut*/ + NULL, /*SOF */ + NULL, + NULL, + USBD_GetCfgDesc_impl, + USBD_GetCfgDesc_impl, + USBD_GetCfgDesc_impl, + USBD_GetDeviceQualifierDesc_impl, }; -#endif // HAVE_IO_U2F - -static USBD_ClassTypeDef const USBD_HID = -{ - USBD_HID_Init, - USBD_HID_DeInit, - USBD_HID_Setup, - NULL, /*EP0_TxSent*/ - NULL, /*EP0_RxReady*/ /* STATUS STAGE IN */ - USBD_HID_DataIn_impl, /*DataIn*/ - USBD_HID_DataOut_impl, /*DataOut*/ - NULL, /*SOF */ - NULL, - NULL, - USBD_GetCfgDesc_impl, - USBD_GetCfgDesc_impl, - USBD_GetCfgDesc_impl, - USBD_GetDeviceQualifierDesc_impl, +#endif // HAVE_IO_U2F + +static USBD_ClassTypeDef const USBD_HID = { + USBD_HID_Init, + USBD_HID_DeInit, + USBD_HID_Setup, + NULL, /*EP0_TxSent*/ + NULL, + /*EP0_RxReady*/ /* STATUS STAGE IN */ + USBD_HID_DataIn_impl, /*DataIn*/ + USBD_HID_DataOut_impl, /*DataOut*/ + NULL, /*SOF */ + NULL, + NULL, + USBD_GetCfgDesc_impl, + USBD_GetCfgDesc_impl, + USBD_GetCfgDesc_impl, + USBD_GetDeviceQualifierDesc_impl, }; #ifdef HAVE_WEBUSB +// clang-format off static const unsigned char C_winusb_string_descriptor[] = { // bLength 0x12, @@ -1310,16 +1296,18 @@ static const unsigned char C_winusb_string_descriptor[] = { // wData 'M', 0x00, 'S', 0x00, 'F', 0x00, 'T', 0x00, '1', 0x00, '0', 0x00, '0', 0x00, WINUSB_VENDOR_CODE, 0x00, // MSFT100 }; +// clang-format on // Microsoft OS 2.0 descriptor wIndex values #define MS_OS_20_DESCRIPTOR_INDEX 0x07 // Microsoft OS 2.0 descriptor types #define MS_OS_20_SUBSET_HEADER_CONFIGURATION 0x01 -#define MS_OS_20_SUBSET_HEADER_FUNCTION 0x02 -#define MS_OS_20_FEATURE_COMPATIBLE_ID 0x03 -#define MS_OS_20_FEATURE_REG_PROPERTY 0x04 +#define MS_OS_20_SUBSET_HEADER_FUNCTION 0x02 +#define MS_OS_20_FEATURE_COMPATIBLE_ID 0x03 +#define MS_OS_20_FEATURE_REG_PROPERTY 0x04 +// clang-format off static const unsigned char C_winusb_request_descriptor[] = { // Microsoft OS 2.0 descriptor set header (table 10) 0x0A, @@ -1412,160 +1400,167 @@ static const unsigned char C_winusb_guid[] = { '4', 0x00, '6', 0x00, '7', 0x00, '6', 0x00, '5', 0x00, '7', 0x00, '2', 0x00, '}', 0x00, 0x00, 0x00, 0x00, 0x00 // propertyData, double unicode nul terminated }; +// clang-format on // upon unsupported request, check for webusb request -void USBD_CtlError( USBD_HandleTypeDef *pdev , USBD_SetupReqTypedef *req) { +void USBD_CtlError(USBD_HandleTypeDef *pdev, USBD_SetupReqTypedef *req) +{ #if WEBUSB_URL_SIZE_B > 0 - if ((req->bmRequest & 0x80) && req->bRequest == WEBUSB_VENDOR_CODE && req->wIndex == WEBUSB_REQ_GET_URL - // HTTPS url - && req->wValue == 1) { - // return the URL descriptor - USBD_CtlSendData (pdev, (unsigned char*)C_webusb_url_descriptor, MIN(req->wLength, sizeof(C_webusb_url_descriptor))); - } - else -#endif // WEBUSB_URL_SIZE_B - // SETUP (LE): 0x80 0x06 0x03 0x77 0x00 0x00 0xXX 0xXX - if ((req->bmRequest & 0x80) - && req->bRequest == USB_REQ_GET_DESCRIPTOR - && (req->wValue>>8) == USB_DESC_TYPE_STRING - && (req->wValue & 0xFF) == 0xEE) { - USBD_CtlSendData(pdev, (unsigned char*)C_winusb_string_descriptor, MIN(req->wLength, sizeof(C_winusb_string_descriptor))); - } - // SETUP (LE): 0x80 0x77 0x04 0x00 0x00 0x00 0xXX 0xXX - else if ((req->bmRequest & 0x80) - && req->bRequest == WINUSB_VENDOR_CODE - && req->wIndex == WINUSB_GET_COMPATIBLE_ID_FEATURE) { - USBD_CtlSendData(pdev, (unsigned char*)C_winusb_wcid, MIN(req->wLength, sizeof(C_winusb_wcid))); - } - // SETUP (LE): 0x80 0x77 0x05 0x00 0x00 0x00 0xXX 0xXX - else if ((req->bmRequest & 0x80) - && req->bRequest == WINUSB_VENDOR_CODE - && req->wIndex == WINUSB_GET_EXTENDED_PROPERTIES_OS_FEATURE - ) { - USBD_CtlSendData(pdev, (unsigned char*)C_winusb_guid, MIN(req->wLength, sizeof(C_winusb_guid))); - } - // Microsoft OS 2.0 Descriptors for Windows 8.1 and Windows 10 - else if ((req->bmRequest & 0x80) - && req->bRequest == WINUSB_VENDOR_CODE - && req->wIndex == MS_OS_20_DESCRIPTOR_INDEX) { - USBD_CtlSendData(pdev, (unsigned char*)C_winusb_request_descriptor, MIN(req->wLength, sizeof(C_winusb_request_descriptor))); - } - else { - USBD_CtlStall(pdev); - } + if ((req->bmRequest & 0x80) && req->bRequest == WEBUSB_VENDOR_CODE + && req->wIndex == WEBUSB_REQ_GET_URL + // HTTPS url + && req->wValue == 1) { + // return the URL descriptor + USBD_CtlSendData(pdev, + (unsigned char *) C_webusb_url_descriptor, + MIN(req->wLength, sizeof(C_webusb_url_descriptor))); + } + else +#endif // WEBUSB_URL_SIZE_B + // SETUP (LE): 0x80 0x06 0x03 0x77 0x00 0x00 0xXX 0xXX + if ((req->bmRequest & 0x80) && req->bRequest == USB_REQ_GET_DESCRIPTOR + && (req->wValue >> 8) == USB_DESC_TYPE_STRING && (req->wValue & 0xFF) == 0xEE) { + USBD_CtlSendData(pdev, + (unsigned char *) C_winusb_string_descriptor, + MIN(req->wLength, sizeof(C_winusb_string_descriptor))); + } + // SETUP (LE): 0x80 0x77 0x04 0x00 0x00 0x00 0xXX 0xXX + else if ((req->bmRequest & 0x80) && req->bRequest == WINUSB_VENDOR_CODE + && req->wIndex == WINUSB_GET_COMPATIBLE_ID_FEATURE) { + USBD_CtlSendData( + pdev, (unsigned char *) C_winusb_wcid, MIN(req->wLength, sizeof(C_winusb_wcid))); + } + // SETUP (LE): 0x80 0x77 0x05 0x00 0x00 0x00 0xXX 0xXX + else if ((req->bmRequest & 0x80) && req->bRequest == WINUSB_VENDOR_CODE + && req->wIndex == WINUSB_GET_EXTENDED_PROPERTIES_OS_FEATURE) { + USBD_CtlSendData( + pdev, (unsigned char *) C_winusb_guid, MIN(req->wLength, sizeof(C_winusb_guid))); + } + // Microsoft OS 2.0 Descriptors for Windows 8.1 and Windows 10 + else if ((req->bmRequest & 0x80) && req->bRequest == WINUSB_VENDOR_CODE + && req->wIndex == MS_OS_20_DESCRIPTOR_INDEX) { + USBD_CtlSendData(pdev, + (unsigned char *) C_winusb_request_descriptor, + MIN(req->wLength, sizeof(C_winusb_request_descriptor))); + } + else { + USBD_CtlStall(pdev); + } } -static const USBD_ClassTypeDef USBD_WEBUSB = -{ - USBD_WEBUSB_Init, - USBD_WEBUSB_DeInit, - USBD_WEBUSB_Setup, - NULL, /*EP0_TxSent*/ - NULL, /*EP0_RxReady*/ - USBD_WEBUSB_DataIn, - USBD_WEBUSB_DataOut, - NULL, /*SOF */ - NULL, /*ISOIn*/ - NULL, /*ISOOut*/ - USBD_GetCfgDesc_impl, - USBD_GetCfgDesc_impl, - USBD_GetCfgDesc_impl, - USBD_GetDeviceQualifierDesc_impl, +static const USBD_ClassTypeDef USBD_WEBUSB = { + USBD_WEBUSB_Init, + USBD_WEBUSB_DeInit, + USBD_WEBUSB_Setup, + NULL, /*EP0_TxSent*/ + NULL, /*EP0_RxReady*/ + USBD_WEBUSB_DataIn, + USBD_WEBUSB_DataOut, + NULL, /*SOF */ + NULL, /*ISOIn*/ + NULL, /*ISOOut*/ + USBD_GetCfgDesc_impl, + USBD_GetCfgDesc_impl, + USBD_GetCfgDesc_impl, + USBD_GetDeviceQualifierDesc_impl, }; -#endif // HAVE_WEBUSB +#endif // HAVE_WEBUSB #ifdef HAVE_USB_CLASS_CCID -static const USBD_ClassTypeDef USBD_CCID = -{ - USBD_CCID_Init, - USBD_CCID_DeInit, - USBD_CCID_Setup, - NULL, /*EP0_TxSent*/ - NULL, /*EP0_RxReady*/ - USBD_CCID_DataIn, - USBD_CCID_DataOut, - NULL, /*SOF */ - NULL, /*ISOIn*/ - NULL, /*ISOOut*/ - USBD_GetCfgDesc_impl, - USBD_GetCfgDesc_impl, - USBD_GetCfgDesc_impl, - USBD_GetDeviceQualifierDesc_impl, +static const USBD_ClassTypeDef USBD_CCID = { + USBD_CCID_Init, + USBD_CCID_DeInit, + USBD_CCID_Setup, + NULL, /*EP0_TxSent*/ + NULL, /*EP0_RxReady*/ + USBD_CCID_DataIn, + USBD_CCID_DataOut, + NULL, /*SOF */ + NULL, /*ISOIn*/ + NULL, /*ISOOut*/ + USBD_GetCfgDesc_impl, + USBD_GetCfgDesc_impl, + USBD_GetCfgDesc_impl, + USBD_GetDeviceQualifierDesc_impl, }; -uint8_t SC_AnswerToReset (uint8_t voltage, uint8_t* atr_buffer) { - UNUSED(voltage); - // return the atr length - atr_buffer[0] = 0x3B; - atr_buffer[1] = 0; - return 2; +uint8_t SC_AnswerToReset(uint8_t voltage, uint8_t *atr_buffer) +{ + UNUSED(voltage); + // return the atr length + atr_buffer[0] = 0x3B; + atr_buffer[1] = 0; + return 2; } -void SC_Poweroff(void) { - // nothing to do ? +void SC_Poweroff(void) +{ + // nothing to do ? } -uint8_t SC_ExecuteEscape (uint8_t* escapePtr, uint32_t escapeLen, - uint8_t* responseBuff, - uint16_t* responseLen) { - UNUSED(escapePtr); - UNUSED(escapeLen); - UNUSED(responseBuff); - UNUSED(responseLen); - // nothing to do ? - return 0; +uint8_t SC_ExecuteEscape(uint8_t *escapePtr, + uint32_t escapeLen, + uint8_t *responseBuff, + uint16_t *responseLen) +{ + UNUSED(escapePtr); + UNUSED(escapeLen); + UNUSED(responseBuff); + UNUSED(responseLen); + // nothing to do ? + return 0; } -#endif // HAVE_USB_CLASS_CCID +#endif // HAVE_USB_CLASS_CCID -void USB_power(unsigned char enabled) { - memset(&USBD_Device, 0, sizeof(USBD_Device)); +void USB_power(unsigned char enabled) +{ + memset(&USBD_Device, 0, sizeof(USBD_Device)); - // init timeouts and other global fields - memset(G_io_app.usb_ep_xfer_len, 0, sizeof(G_io_app.usb_ep_xfer_len)); - memset(G_io_app.usb_ep_timeouts, 0, sizeof(G_io_app.usb_ep_timeouts)); + // init timeouts and other global fields + memset(G_io_app.usb_ep_xfer_len, 0, sizeof(G_io_app.usb_ep_xfer_len)); + memset(G_io_app.usb_ep_timeouts, 0, sizeof(G_io_app.usb_ep_timeouts)); - if (enabled) { - memset(&USBD_Device, 0, sizeof(USBD_Device)); - /* Init Device Library */ - USBD_Init(&USBD_Device, (USBD_DescriptorsTypeDef*)&HID_Desc, 0); + if (enabled) { + memset(&USBD_Device, 0, sizeof(USBD_Device)); + /* Init Device Library */ + USBD_Init(&USBD_Device, (USBD_DescriptorsTypeDef *) &HID_Desc, 0); - /* Register the HID class */ - USBD_RegisterClassForInterface(HID_INTF, &USBD_Device, (USBD_ClassTypeDef*)&USBD_HID); + /* Register the HID class */ + USBD_RegisterClassForInterface(HID_INTF, &USBD_Device, (USBD_ClassTypeDef *) &USBD_HID); #ifdef HAVE_IO_U2F - USBD_RegisterClassForInterface(U2F_INTF, &USBD_Device, (USBD_ClassTypeDef*)&USBD_U2F); - // initialize the U2F tunnel transport - u2f_transport_init(&G_io_u2f, G_io_apdu_buffer, IO_APDU_BUFFER_SIZE); -#endif // HAVE_IO_U2F + USBD_RegisterClassForInterface(U2F_INTF, &USBD_Device, (USBD_ClassTypeDef *) &USBD_U2F); + // initialize the U2F tunnel transport + u2f_transport_init(&G_io_u2f, G_io_apdu_buffer, IO_APDU_BUFFER_SIZE); +#endif // HAVE_IO_U2F #ifdef HAVE_USB_CLASS_CCID - USBD_RegisterClassForInterface(CCID_INTF, &USBD_Device, (USBD_ClassTypeDef*)&USBD_CCID); -#endif // HAVE_USB_CLASS_CCID + USBD_RegisterClassForInterface(CCID_INTF, &USBD_Device, (USBD_ClassTypeDef *) &USBD_CCID); +#endif // HAVE_USB_CLASS_CCID #ifdef HAVE_WEBUSB - USBD_RegisterClassForInterface(WEBUSB_INTF, &USBD_Device, (USBD_ClassTypeDef*)&USBD_WEBUSB); -#endif // HAVE_WEBUSB + USBD_RegisterClassForInterface( + WEBUSB_INTF, &USBD_Device, (USBD_ClassTypeDef *) &USBD_WEBUSB); +#endif // HAVE_WEBUSB - /* Start Device Process */ - USBD_Start(&USBD_Device); - } - else { - USBD_DeInit(&USBD_Device); - } + /* Start Device Process */ + USBD_Start(&USBD_Device); + } + else { + USBD_DeInit(&USBD_Device); + } } #pragma GCC diagnostic pop /** - * @} - */ - + * @} + */ /** - * @} - */ - + * @} + */ /** - * @} - */ + * @} + */ /************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/ diff --git a/lib_u2f/include/u2f_io.h b/lib_u2f/include/u2f_io.h index 47f9f1f2a..2d3dd4ab8 100644 --- a/lib_u2f/include/u2f_io.h +++ b/lib_u2f/include/u2f_io.h @@ -1,20 +1,20 @@ /******************************************************************************* -* Ledger Nano S - Secure firmware -* (c) 2022 Ledger -* -* Licensed under the Apache License, Version 2.0 (the "License"); -* you may not use this file except in compliance with the License. -* You may obtain a copy of the License at -* -* http://www.apache.org/licenses/LICENSE-2.0 -* -* Unless required by applicable law or agreed to in writing, software -* distributed under the License is distributed on an "AS IS" BASIS, -* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -* See the License for the specific language governing permissions and -* limitations under the License. -********************************************************************************/ + * Ledger Nano S - Secure firmware + * (c) 2022 Ledger + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT 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 diff --git a/lib_u2f/include/u2f_processing.h b/lib_u2f/include/u2f_processing.h index 3b5471478..0ece64c78 100644 --- a/lib_u2f/include/u2f_processing.h +++ b/lib_u2f/include/u2f_processing.h @@ -1,20 +1,20 @@ /******************************************************************************* -* Ledger Nano S - Secure firmware -* (c) 2022 Ledger -* -* Licensed under the Apache License, Version 2.0 (the "License"); -* you may not use this file except in compliance with the License. -* You may obtain a copy of the License at -* -* http://www.apache.org/licenses/LICENSE-2.0 -* -* Unless required by applicable law or agreed to in writing, software -* distributed under the License is distributed on an "AS IS" BASIS, -* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -* See the License for the specific language governing permissions and -* limitations under the License. -********************************************************************************/ + * Ledger Nano S - Secure firmware + * (c) 2022 Ledger + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT 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 __U2F_PROCESSING_H__ @@ -35,15 +35,16 @@ void u2f_timeout(u2f_service_t *service); /** * Auto reply user presence required until the real reply is ready to be replied */ -void u2f_message_set_autoreply_wait_user_presence(u2f_service_t* service, bool enabled); +void u2f_message_set_autoreply_wait_user_presence(u2f_service_t *service, bool enabled); /** * Return true when a message can be replied using ::u2f_message_reply */ -bool u2f_message_repliable(u2f_service_t* service); +bool u2f_message_repliable(u2f_service_t *service); /** - * Function to be called by the user when the reply to a previously completed message is ready to be sent + * Function to be called by the user when the reply to a previously completed message is ready to be + * sent */ void u2f_message_reply(u2f_service_t *service, uint8_t cmd, uint8_t *buffer, uint16_t length); diff --git a/lib_u2f/include/u2f_service.h b/lib_u2f/include/u2f_service.h index 80869d637..11c3752c6 100644 --- a/lib_u2f/include/u2f_service.h +++ b/lib_u2f/include/u2f_service.h @@ -1,20 +1,20 @@ /******************************************************************************* -* Ledger Nano S - Secure firmware -* (c) 2022 Ledger -* -* Licensed under the Apache License, Version 2.0 (the "License"); -* you may not use this file except in compliance with the License. -* You may obtain a copy of the License at -* -* http://www.apache.org/licenses/LICENSE-2.0 -* -* Unless required by applicable law or agreed to in writing, software -* distributed under the License is distributed on an "AS IS" BASIS, -* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -* See the License for the specific language governing permissions and -* limitations under the License. -********************************************************************************/ + * Ledger Nano S - Secure firmware + * (c) 2022 Ledger + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT 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 @@ -28,11 +28,10 @@ struct u2f_service_t; -typedef void (*u2fHandle_t)(struct u2f_service_t *service, uint8_t *inputBuffer, - uint8_t *channel); +typedef void (*u2fHandle_t)(struct u2f_service_t *service, uint8_t *inputBuffer, uint8_t *channel); typedef void (*u2fPromptUserPresence_t)(struct u2f_service_t *service, - bool enroll, - uint8_t *applicationParameter); + bool enroll, + uint8_t *applicationParameter); typedef void (*u2fTimer_t)(struct u2f_service_t *service); typedef enum { @@ -62,7 +61,7 @@ typedef struct u2f_service_t { // Internal uint32_t next_channel; - uint8_t channel[U2F_CHANNEL_ID_SIZE]; + uint8_t channel[U2F_CHANNEL_ID_SIZE]; u2f_transport_media_t media; // buffer reference used when transport layer is reset, to process and receive the next message @@ -70,32 +69,32 @@ typedef struct u2f_service_t { // length of the receive buffer to avoid overflows uint16_t transportReceiveBufferLength; - uint8_t transportChannel[4]; - uint16_t transportOffset; - uint16_t transportLength; - uint8_t transportPacketIndex; - uint8_t *transportBuffer; + uint8_t transportChannel[4]; + uint16_t transportOffset; + uint16_t transportLength; + uint8_t transportPacketIndex; + uint8_t *transportBuffer; u2f_transport_state_t transportState; u2f_transport_media_t transportMedia; // handle fake channel state to simulate a USB keepalive - uint16_t fakeChannelTransportOffset; - uint8_t fakeChannelTransportPacketIndex; + uint16_t fakeChannelTransportOffset; + uint8_t fakeChannelTransportPacketIndex; u2f_transport_state_t fakeChannelTransportState; - uint16_t commandCrc; - uint16_t fakeChannelCrc; + uint16_t commandCrc; + uint16_t fakeChannelCrc; // mark that an asynchronous response is available uint8_t waitAsynchronousResponse; - //uint16_t responseLength; + // uint16_t responseLength; bool sending; u2fTimer_t timeoutFunction; - uint32_t timerInterval; - uint32_t seqTimeout; - bool requireKeepalive; - uint32_t keepaliveTimeout; + uint32_t timerInterval; + uint32_t seqTimeout; + bool requireKeepalive; + uint32_t keepaliveTimeout; uint8_t sendCmd; } u2f_service_t; diff --git a/lib_u2f/include/u2f_timer.h b/lib_u2f/include/u2f_timer.h index b21920da8..3bc2de45f 100644 --- a/lib_u2f/include/u2f_timer.h +++ b/lib_u2f/include/u2f_timer.h @@ -1,20 +1,20 @@ /******************************************************************************* -* Ledger Nano S - Secure firmware -* (c) 2022 Ledger -* -* Licensed under the Apache License, Version 2.0 (the "License"); -* you may not use this file except in compliance with the License. -* You may obtain a copy of the License at -* -* http://www.apache.org/licenses/LICENSE-2.0 -* -* Unless required by applicable law or agreed to in writing, software -* distributed under the License is distributed on an "AS IS" BASIS, -* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -* See the License for the specific language governing permissions and -* limitations under the License. -********************************************************************************/ + * Ledger Nano S - Secure firmware + * (c) 2022 Ledger + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT 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 diff --git a/lib_u2f/include/u2f_transport.h b/lib_u2f/include/u2f_transport.h index 86050fffa..6b88b6253 100644 --- a/lib_u2f/include/u2f_transport.h +++ b/lib_u2f/include/u2f_transport.h @@ -1,20 +1,20 @@ /******************************************************************************* -* Ledger Nano S - Secure firmware -* (c) 2022 Ledger -* -* Licensed under the Apache License, Version 2.0 (the "License"); -* you may not use this file except in compliance with the License. -* You may obtain a copy of the License at -* -* http://www.apache.org/licenses/LICENSE-2.0 -* -* Unless required by applicable law or agreed to in writing, software -* distributed under the License is distributed on an "AS IS" BASIS, -* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -* See the License for the specific language governing permissions and -* limitations under the License. -********************************************************************************/ + * Ledger Nano S - Secure firmware + * (c) 2022 Ledger + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT 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 __U2F_TRANSPORT_H__ @@ -23,10 +23,10 @@ #include "u2f_service.h" // Shared commands -#define U2F_CMD_PING 0x81 -#define U2F_CMD_MSG 0x83 -#define CTAP2_CMD_CBOR 0x90 // FIDO2 -#define CTAP2_CMD_CANCEL 0x91 // FIDO2 +#define U2F_CMD_PING 0x81 +#define U2F_CMD_MSG 0x83 +#define CTAP2_CMD_CBOR 0x90 // FIDO2 +#define CTAP2_CMD_CANCEL 0x91 // FIDO2 // USB only commands #define U2F_CMD_INIT 0x86 @@ -34,80 +34,84 @@ #define U2F_CMD_WINK 0x88 // BLE only commands -#define U2F_CMD_KEEPALIVE 0x82 +#define U2F_CMD_KEEPALIVE 0x82 #define KEEPALIVE_REASON_PROCESSING 0x01 #define KEEPALIVE_REASON_TUP_NEEDED 0x02 -#define U2F_STATUS_ERROR 0xBF -#define CTAP2_STATUS_KEEPALIVE 0xBB // FIDO2 +#define U2F_STATUS_ERROR 0xBF +#define CTAP2_STATUS_KEEPALIVE 0xBB // FIDO2 // Shared errors -#define ERROR_NONE 0x00 -#define ERROR_INVALID_CMD 0x01 -#define ERROR_INVALID_PAR 0x02 -#define ERROR_INVALID_LEN 0x03 -#define ERROR_INVALID_SEQ 0x04 -#define ERROR_MSG_TIMEOUT 0x05 -#define ERROR_OTHER 0x7f +#define ERROR_NONE 0x00 +#define ERROR_INVALID_CMD 0x01 +#define ERROR_INVALID_PAR 0x02 +#define ERROR_INVALID_LEN 0x03 +#define ERROR_INVALID_SEQ 0x04 +#define ERROR_MSG_TIMEOUT 0x05 +#define ERROR_OTHER 0x7f // USB only errors -#define ERROR_CHANNEL_BUSY 0x06 -#define ERROR_LOCK_REQUIRED 0x0a -#define ERROR_INVALID_CID 0x0b +#define ERROR_CHANNEL_BUSY 0x06 +#define ERROR_LOCK_REQUIRED 0x0a +#define ERROR_INVALID_CID 0x0b // CTAP2 errors -#define ERROR_CBOR_UNEXPECTED_TYPE 0x11 -#define ERROR_INVALID_CBOR 0x12 -#define ERROR_MISSING_PARAMETER 0x14 -#define ERROR_LIMIT_EXCEEDED 0x15 -#define ERROR_UNSUPPORTED_EXTENSION 0x16 -#define ERROR_CREDENTIAL_EXCLUDED 0x19 -#define ERROR_PROCESSING 0x21 -#define ERROR_INVALID_CREDENTIAL 0x22 -#define ERROR_USER_ACTION_PENDING 0x23 -#define ERROR_OPERATION_PENDING 0x24 -#define ERROR_NO_OPERATIONS 0x25 -#define ERROR_UNSUPPORTED_ALGORITHM 0x26 -#define ERROR_OPERATION_DENIED 0x27 -#define ERROR_KEY_STORE_FULL 0x28 -#define ERROR_NO_OPERATION_PENDING 0x2A -#define ERROR_UNSUPPORTED_OPTION 0x2B -#define ERROR_INVALID_OPTION 0x2C -#define ERROR_KEEPALIVE_CANCEL 0x2D -#define ERROR_NO_CREDENTIALS 0x2E -#define ERROR_USER_ACTION_TIMEOUT 0x2F -#define ERROR_NOT_ALLOWED 0x30 -#define ERROR_PIN_INVALID 0x31 -#define ERROR_PIN_BLOCKED 0x32 -#define ERROR_PIN_AUTH_INVALID 0x33 -#define ERROR_PIN_AUTH_BLOCKED 0x34 -#define ERROR_PIN_NOT_SET 0x35 -#define ERROR_PIN_REQUIRED 0x36 -#define ERROR_PIN_POLICY_VIOLATION 0x37 -#define ERROR_PIN_TOKEN_EXPIRED 0x38 -#define ERROR_REQUEST_TOO_LARGE 0x39 -#define ERROR_ACTION_TIMEOUT 0x3A -#define ERROR_UP_REQUIRED 0x3B +#define ERROR_CBOR_UNEXPECTED_TYPE 0x11 +#define ERROR_INVALID_CBOR 0x12 +#define ERROR_MISSING_PARAMETER 0x14 +#define ERROR_LIMIT_EXCEEDED 0x15 +#define ERROR_UNSUPPORTED_EXTENSION 0x16 +#define ERROR_CREDENTIAL_EXCLUDED 0x19 +#define ERROR_PROCESSING 0x21 +#define ERROR_INVALID_CREDENTIAL 0x22 +#define ERROR_USER_ACTION_PENDING 0x23 +#define ERROR_OPERATION_PENDING 0x24 +#define ERROR_NO_OPERATIONS 0x25 +#define ERROR_UNSUPPORTED_ALGORITHM 0x26 +#define ERROR_OPERATION_DENIED 0x27 +#define ERROR_KEY_STORE_FULL 0x28 +#define ERROR_NO_OPERATION_PENDING 0x2A +#define ERROR_UNSUPPORTED_OPTION 0x2B +#define ERROR_INVALID_OPTION 0x2C +#define ERROR_KEEPALIVE_CANCEL 0x2D +#define ERROR_NO_CREDENTIALS 0x2E +#define ERROR_USER_ACTION_TIMEOUT 0x2F +#define ERROR_NOT_ALLOWED 0x30 +#define ERROR_PIN_INVALID 0x31 +#define ERROR_PIN_BLOCKED 0x32 +#define ERROR_PIN_AUTH_INVALID 0x33 +#define ERROR_PIN_AUTH_BLOCKED 0x34 +#define ERROR_PIN_NOT_SET 0x35 +#define ERROR_PIN_REQUIRED 0x36 +#define ERROR_PIN_POLICY_VIOLATION 0x37 +#define ERROR_PIN_TOKEN_EXPIRED 0x38 +#define ERROR_REQUEST_TOO_LARGE 0x39 +#define ERROR_ACTION_TIMEOUT 0x3A +#define ERROR_UP_REQUIRED 0x3B // Proprietary errors -#define ERROR_PROP_UNKNOWN_COMMAND 0x80 -#define ERROR_PROP_COMMAND_TOO_LONG 0x81 -#define ERROR_PROP_INVALID_CONTINUATION 0x82 -#define ERROR_PROP_UNEXPECTED_CONTINUATION 0x83 -#define ERROR_PROP_CONTINUATION_OVERFLOW 0x84 -#define ERROR_PROP_MESSAGE_TOO_SHORT 0x85 -#define ERROR_PROP_UNCONSISTENT_MSG_LENGTH 0x86 -#define ERROR_PROP_UNSUPPORTED_MSG_APDU 0x87 +#define ERROR_PROP_UNKNOWN_COMMAND 0x80 +#define ERROR_PROP_COMMAND_TOO_LONG 0x81 +#define ERROR_PROP_INVALID_CONTINUATION 0x82 +#define ERROR_PROP_UNEXPECTED_CONTINUATION 0x83 +#define ERROR_PROP_CONTINUATION_OVERFLOW 0x84 +#define ERROR_PROP_MESSAGE_TOO_SHORT 0x85 +#define ERROR_PROP_UNCONSISTENT_MSG_LENGTH 0x86 +#define ERROR_PROP_UNSUPPORTED_MSG_APDU 0x87 #define ERROR_PROP_INVALID_DATA_LENGTH_APDU 0x88 -#define ERROR_PROP_INTERNAL_ERROR_APDU 0x89 -#define ERROR_PROP_INVALID_PARAMETERS_APDU 0x8A -#define ERROR_PROP_INVALID_DATA_APDU 0x8B -#define ERROR_PROP_DEVICE_NOT_SETUP 0x8C -#define ERROR_PROP_MEDIA_MIXED 0x8D -#define ERROR_PROP_RPID_MEDIA_DENIED 0x8E +#define ERROR_PROP_INTERNAL_ERROR_APDU 0x89 +#define ERROR_PROP_INVALID_PARAMETERS_APDU 0x8A +#define ERROR_PROP_INVALID_DATA_APDU 0x8B +#define ERROR_PROP_DEVICE_NOT_SETUP 0x8C +#define ERROR_PROP_MEDIA_MIXED 0x8D +#define ERROR_PROP_RPID_MEDIA_DENIED 0x8E /** * Initialize the U2F transport library - * Incoming messages are store in the provided message buffer. It can be overlapped with io APDU buffer to save RAM (but won't allow for multiple IO model (no mutual exclusion in the buffer access)) + * Incoming messages are store in the provided message buffer. It can be overlapped with io APDU + * buffer to save RAM (but won't allow for multiple IO model (no mutual exclusion in the buffer + * access)) */ -void u2f_transport_init(u2f_service_t *service, uint8_t* message_buffer, uint16_t message_buffer_length); +void u2f_transport_init(u2f_service_t *service, + uint8_t *message_buffer, + uint16_t message_buffer_length); /** * Function to be called when an IO message has been sent. @@ -117,8 +121,10 @@ void u2f_transport_sent(u2f_service_t *service, u2f_transport_media_t media); /** * Function to be called when an IO message has been received. */ -void u2f_transport_received(u2f_service_t *service, uint8_t *buffer, - uint16_t size, u2f_transport_media_t media); +void u2f_transport_received(u2f_service_t *service, + uint8_t *buffer, + uint16_t size, + u2f_transport_media_t media); /** * Returns 0 if the provided channel buffer is not a broadcast channel diff --git a/lib_u2f/src/u2f_transport.c b/lib_u2f/src/u2f_transport.c index c62c63106..4334fdd5c 100644 --- a/lib_u2f/src/u2f_transport.c +++ b/lib_u2f/src/u2f_transport.c @@ -1,20 +1,20 @@ /******************************************************************************* -* Ledger Nano S - Secure firmware -* (c) 2022 Ledger -* -* Licensed under the Apache License, Version 2.0 (the "License"); -* you may not use this file except in compliance with the License. -* You may obtain a copy of the License at -* -* http://www.apache.org/licenses/LICENSE-2.0 -* -* Unless required by applicable law or agreed to in writing, software -* distributed under the License is distributed on an "AS IS" BASIS, -* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -* See the License for the specific language governing permissions and -* limitations under the License. -********************************************************************************/ + * Ledger Nano S - Secure firmware + * (c) 2022 Ledger + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + ********************************************************************************/ #ifdef HAVE_IO_U2F @@ -30,7 +30,7 @@ #include "os.h" #include "os_io_seproxyhal.h" -#define U2F_MASK_COMMAND 0x80 +#define U2F_MASK_COMMAND 0x80 #define U2F_COMMAND_HEADER_SIZE 3 static const uint8_t BROADCAST_CHANNEL[] = {0xff, 0xff, 0xff, 0xff}; @@ -41,17 +41,19 @@ static const uint8_t FORBIDDEN_CHANNEL[] = {0x00, 0x00, 0x00, 0x00}; */ // init -void u2f_transport_reset(u2f_service_t* service) { - service->transportState = U2F_IDLE; - service->transportOffset = 0; - service->transportMedia = 0; - service->transportPacketIndex = 0; - service->fakeChannelTransportState = U2F_IDLE; - service->fakeChannelTransportOffset = 0; +void u2f_transport_reset(u2f_service_t *service) +{ + service->transportState = U2F_IDLE; + service->transportOffset = 0; + service->transportMedia = 0; + service->transportPacketIndex = 0; + service->fakeChannelTransportState = U2F_IDLE; + service->fakeChannelTransportOffset = 0; service->fakeChannelTransportPacketIndex = 0; - service->sending = false; - service->waitAsynchronousResponse = U2F_WAIT_ASYNCH_IDLE; - // reset the receive buffer to allow for a new message to be received again (in case transmission of a CODE buffer the previous reply) + service->sending = false; + service->waitAsynchronousResponse = U2F_WAIT_ASYNCH_IDLE; + // reset the receive buffer to allow for a new message to be received again (in case + // transmission of a CODE buffer the previous reply) service->transportBuffer = service->transportReceiveBuffer; cx_rng(service->channel, U2F_CHANNEL_ID_SIZE); } @@ -59,9 +61,12 @@ void u2f_transport_reset(u2f_service_t* service) { /** * Initialize the u2f transport and provide the buffer into which to store incoming message */ -void u2f_transport_init(u2f_service_t *service, uint8_t* message_buffer, uint16_t message_buffer_length) { - service->next_channel = 1; - service->transportReceiveBuffer = message_buffer; +void u2f_transport_init(u2f_service_t *service, + uint8_t *message_buffer, + uint16_t message_buffer_length) +{ + service->next_channel = 1; + service->transportReceiveBuffer = message_buffer; service->transportReceiveBufferLength = message_buffer_length; u2f_transport_reset(service); } @@ -69,27 +74,30 @@ void u2f_transport_init(u2f_service_t *service, uint8_t* message_buffer, uint16_ /** * Reply an error at the U2F transport level (take into account the FIDO U2F framing) */ -static void u2f_transport_error(u2f_service_t *service, char errorCode) { - //u2f_transport_reset(service); // warning reset first to allow for U2F_io sent call to u2f_transport_sent internally on eventless platforms +static void u2f_transport_error(u2f_service_t *service, char errorCode) +{ + // u2f_transport_reset(service); // warning reset first to allow for U2F_io sent call to + // u2f_transport_sent internally on eventless platforms G_io_usb_ep_buffer[8] = errorCode; - // ensure the state is set to error sending to allow for special treatment in case reply is not read by the receiver - service->transportState = U2F_SENDING_ERROR; + // ensure the state is set to error sending to allow for special treatment in case reply is not + // read by the receiver + service->transportState = U2F_SENDING_ERROR; service->transportPacketIndex = 0; - service->transportBuffer = G_io_usb_ep_buffer + 8; - service->transportOffset = 0; - service->transportLength = 1; - service->sendCmd = U2F_STATUS_ERROR; + service->transportBuffer = G_io_usb_ep_buffer + 8; + service->transportOffset = 0; + service->transportLength = 1; + service->sendCmd = U2F_STATUS_ERROR; // pump the first message, with the reception media u2f_transport_sent(service, service->media); } /** - * Function called when the previously scheduled message to be sent on the media is effectively sent. - * And a new message can be scheduled. + * Function called when the previously scheduled message to be sent on the media is effectively + * sent. And a new message can be scheduled. */ -void u2f_transport_sent(u2f_service_t* service, u2f_transport_media_t media) { - +void u2f_transport_sent(u2f_service_t *service, u2f_transport_media_t media) +{ // don't process when replying to anti timeout requests if (!u2f_message_repliable(service)) { // previous mark packet as sent @@ -105,22 +113,20 @@ void u2f_transport_sent(u2f_service_t* service, u2f_transport_media_t media) { && service->transportState != U2F_SENDING_ERROR) { // absorb the error, transport is erroneous but that won't hurt in the end. // also absorb the fake channel user presence check reply ack - //THROW(INVALID_STATE); + // THROW(INVALID_STATE); return; } if (service->transportOffset < service->transportLength) { - uint16_t mtu = (media == U2F_MEDIA_USB) ? USB_SEGMENT_SIZE : BLE_SEGMENT_SIZE; - uint16_t channelHeader = - (media == U2F_MEDIA_USB ? 4 : 0); - uint8_t headerSize = - (service->transportPacketIndex == 0 ? (channelHeader + 3) - : (channelHeader + 1)); - uint16_t blockSize = ((service->transportLength - service->transportOffset) > - (mtu - headerSize) - ? (mtu - headerSize) - : service->transportLength - service->transportOffset); + uint16_t mtu = (media == U2F_MEDIA_USB) ? USB_SEGMENT_SIZE : BLE_SEGMENT_SIZE; + uint16_t channelHeader = (media == U2F_MEDIA_USB ? 4 : 0); + uint8_t headerSize + = (service->transportPacketIndex == 0 ? (channelHeader + 3) : (channelHeader + 1)); + uint16_t blockSize + = ((service->transportLength - service->transportOffset) > (mtu - headerSize) + ? (mtu - headerSize) + : service->transportLength - service->transportOffset); uint16_t dataSize = blockSize + headerSize; - uint16_t offset = 0; + uint16_t offset = 0; // Fragment if (media == U2F_MEDIA_USB) { memcpy(G_io_usb_ep_buffer, service->channel, U2F_CHANNEL_ID_SIZE); @@ -130,12 +136,14 @@ void u2f_transport_sent(u2f_service_t* service, u2f_transport_media_t media) { G_io_usb_ep_buffer[offset++] = service->sendCmd; G_io_usb_ep_buffer[offset++] = (service->transportLength >> 8); G_io_usb_ep_buffer[offset++] = (service->transportLength & 0xff); - } else { + } + else { G_io_usb_ep_buffer[offset++] = (service->transportPacketIndex - 1); } if (service->transportBuffer != NULL) { memmove(G_io_usb_ep_buffer + headerSize, - service->transportBuffer + service->transportOffset, blockSize); + service->transportBuffer + service->transportOffset, + blockSize); } service->transportOffset += blockSize; service->transportPacketIndex++; @@ -144,13 +152,15 @@ void u2f_transport_sent(u2f_service_t* service, u2f_transport_media_t media) { // last part sent else if (service->transportOffset == service->transportLength) { u2f_transport_reset(service); - // we sent the whole response (even if we haven't yet received the ack for the last sent usb in packet) + // we sent the whole response (even if we haven't yet received the ack for the last sent usb + // in packet) G_io_app.apdu_state = APDU_IDLE; } } -void u2f_transport_send_usb_user_presence_required(u2f_service_t *service) { - uint16_t offset = 0; +void u2f_transport_send_usb_user_presence_required(u2f_service_t *service) +{ + uint16_t offset = 0; service->sending = true; memcpy(G_io_usb_ep_buffer, service->channel, U2F_CHANNEL_ID_SIZE); offset += 4; @@ -162,8 +172,9 @@ void u2f_transport_send_usb_user_presence_required(u2f_service_t *service) { u2f_io_send(G_io_usb_ep_buffer, offset, U2F_MEDIA_USB); } -void u2f_transport_send_wink(u2f_service_t *service) { - uint16_t offset = 0; +void u2f_transport_send_wink(u2f_service_t *service) +{ + uint16_t offset = 0; service->sending = true; memcpy(G_io_usb_ep_buffer, service->channel, U2F_CHANNEL_ID_SIZE); offset += 4; @@ -173,11 +184,11 @@ void u2f_transport_send_wink(u2f_service_t *service) { u2f_io_send(G_io_usb_ep_buffer, offset, U2F_MEDIA_USB); } - #ifdef HAVE_FIDO2 -void u2f_transport_ctap2_send_keepalive(u2f_service_t *service, uint8_t reason) { - uint16_t offset = 0; +void u2f_transport_ctap2_send_keepalive(u2f_service_t *service, uint8_t reason) +{ + uint16_t offset = 0; service->sending = true; memcpy(G_io_usb_ep_buffer, service->channel, U2F_CHANNEL_ID_SIZE); offset += 4; @@ -190,7 +201,8 @@ void u2f_transport_ctap2_send_keepalive(u2f_service_t *service, uint8_t reason) #endif -bool u2f_transport_receive_fakeChannel(u2f_service_t *service, uint8_t *buffer, uint16_t size) { +bool u2f_transport_receive_fakeChannel(u2f_service_t *service, uint8_t *buffer, uint16_t size) +{ if (service->fakeChannelTransportState == U2F_INTERNAL_ERROR) { return false; } @@ -198,7 +210,7 @@ bool u2f_transport_receive_fakeChannel(u2f_service_t *service, uint8_t *buffer, goto error; } if (service->fakeChannelTransportOffset == 0) { - uint16_t commandLength = U2BE(buffer, 4+1) + U2F_COMMAND_HEADER_SIZE; + uint16_t commandLength = U2BE(buffer, 4 + 1) + U2F_COMMAND_HEADER_SIZE; // Some buggy implementations can send a WINK here, reply it gently if (buffer[4] == U2F_CMD_WINK) { u2f_transport_send_wink(service); @@ -211,15 +223,17 @@ bool u2f_transport_receive_fakeChannel(u2f_service_t *service, uint8_t *buffer, if (buffer[4] != U2F_CMD_MSG) { goto error; } - service->fakeChannelTransportOffset = MIN(size - 4, service->transportLength); + service->fakeChannelTransportOffset = MIN(size - 4, service->transportLength); service->fakeChannelTransportPacketIndex = 0; - service->fakeChannelCrc = cx_crc16_update(0, buffer + 4, service->fakeChannelTransportOffset); + service->fakeChannelCrc + = cx_crc16_update(0, buffer + 4, service->fakeChannelTransportOffset); } else { if (buffer[4] != service->fakeChannelTransportPacketIndex) { goto error; } - uint16_t xfer_len = MIN(size - 5, service->transportLength - service->fakeChannelTransportOffset); + uint16_t xfer_len + = MIN(size - 5, service->transportLength - service->fakeChannelTransportOffset); service->fakeChannelTransportPacketIndex++; service->fakeChannelTransportOffset += xfer_len; service->fakeChannelCrc = cx_crc16_update(service->fakeChannelCrc, buffer + 5, xfer_len); @@ -228,7 +242,7 @@ bool u2f_transport_receive_fakeChannel(u2f_service_t *service, uint8_t *buffer, if (service->fakeChannelCrc != service->commandCrc) { goto error; } - service->fakeChannelTransportState = U2F_FAKE_RECEIVED; + service->fakeChannelTransportState = U2F_FAKE_RECEIVED; service->fakeChannelTransportOffset = 0; // reply immediately when the asynch response is not yet ready if (service->waitAsynchronousResponse == U2F_WAIT_ASYNCH_ON) { @@ -245,18 +259,21 @@ bool u2f_transport_receive_fakeChannel(u2f_service_t *service, uint8_t *buffer, return false; } - /** * Function that process every message received on a media. * Performs message concatenation when message is split. */ -void u2f_transport_received(u2f_service_t *service, uint8_t *buffer, - uint16_t size, u2f_transport_media_t media) { +void u2f_transport_received(u2f_service_t *service, + uint8_t *buffer, + uint16_t size, + u2f_transport_media_t media) +{ uint16_t channelHeader = (media == U2F_MEDIA_USB ? 4 : 0); uint16_t xfer_len; service->media = media; - //PRINTF("recv %d %d %d %d %d\n", size, service->waitAsynchronousResponse, service->transportState, service->transportOffset, buffer[4]); + // PRINTF("recv %d %d %d %d %d\n", size, service->waitAsynchronousResponse, + // service->transportState, service->transportOffset, buffer[4]); // Handle a busy channel and avoid reentry if (service->transportState == U2F_SENDING_RESPONSE) { @@ -283,7 +300,8 @@ void u2f_transport_received(u2f_service_t *service, uint8_t *buffer, goto error; } if (media == U2F_MEDIA_USB) { - // hold the current channel value to reply to, for example, INIT commands within flow of segments. + // hold the current channel value to reply to, for example, INIT commands within flow of + // segments. memcpy(service->channel, buffer, U2F_CHANNEL_ID_SIZE); } @@ -291,10 +309,12 @@ void u2f_transport_received(u2f_service_t *service, uint8_t *buffer, // Handle a cancel request if received - if ((buffer[channelHeader] == CTAP2_CMD_CANCEL) && - (((media == U2F_MEDIA_USB) && (memcmp(service->transportChannel, service->channel, U2F_CHANNEL_ID_SIZE) == 0)) || - (media != U2F_MEDIA_USB))) { - // Drop the cancel request if there's no command to be processed, otherwise pass it to the upper layer immediately + if ((buffer[channelHeader] == CTAP2_CMD_CANCEL) + && (((media == U2F_MEDIA_USB) + && (memcmp(service->transportChannel, service->channel, U2F_CHANNEL_ID_SIZE) == 0)) + || (media != U2F_MEDIA_USB))) { + // Drop the cancel request if there's no command to be processed, otherwise pass it to the + // upper layer immediately if (service->transportState != U2F_PROCESSING_COMMAND) { return; } @@ -305,11 +325,11 @@ void u2f_transport_received(u2f_service_t *service, uint8_t *buffer, #endif - // no previous chunk processed for the current message if (service->transportOffset == 0 // on USB we could get an INIT within a flow of segments. - || (media == U2F_MEDIA_USB && memcmp(service->transportChannel, service->channel, U2F_CHANNEL_ID_SIZE) != 0) + || (media == U2F_MEDIA_USB + && memcmp(service->transportChannel, service->channel, U2F_CHANNEL_ID_SIZE) != 0) // CTAP2 transport test (HID-1) || (buffer[channelHeader] == U2F_CMD_INIT)) { if (size < (channelHeader + 3)) { @@ -318,22 +338,22 @@ void u2f_transport_received(u2f_service_t *service, uint8_t *buffer, goto error; } // check this is a command, cannot accept continuation without previous command - if ((buffer[channelHeader+0]&U2F_MASK_COMMAND) == 0) { + if ((buffer[channelHeader + 0] & U2F_MASK_COMMAND) == 0) { // Not a command packet, abort - // CTAP2 transport test : do not send back an error in this case (HID-1) - //u2f_transport_error(service, ERROR_INVALID_SEQ); + // CTAP2 transport test : do not send back an error in this case (HID-1) + // u2f_transport_error(service, ERROR_INVALID_SEQ); goto error; } // If waiting for a continuation on a different channel, reply BUSY // immediately if (media == U2F_MEDIA_USB) { - if ((service->transportState == U2F_HANDLE_SEGMENTED) && - (memcmp(service->channel, service->transportChannel, U2F_CHANNEL_ID_SIZE) != - 0) && - (buffer[channelHeader] != U2F_CMD_INIT)) { - // special error case, we reply but don't change the current state of the transport (ongoing message for example) - //u2f_transport_error_no_reset(service, ERROR_CHANNEL_BUSY); + if ((service->transportState == U2F_HANDLE_SEGMENTED) + && (memcmp(service->channel, service->transportChannel, U2F_CHANNEL_ID_SIZE) != 0) + && (buffer[channelHeader] != U2F_CMD_INIT)) { + // special error case, we reply but don't change the current state of the transport + // (ongoing message for example) + // u2f_transport_error_no_reset(service, ERROR_CHANNEL_BUSY); uint16_t offset = 0; // Fragment if (media == U2F_MEDIA_USB) { @@ -350,9 +370,8 @@ void u2f_transport_received(u2f_service_t *service, uint8_t *buffer, } // If a command was already sent, and we are not processing a INIT // command, abort - if ((service->transportState == U2F_HANDLE_SEGMENTED) && - !((media == U2F_MEDIA_USB) && - (buffer[channelHeader] == U2F_CMD_INIT))) { + if ((service->transportState == U2F_HANDLE_SEGMENTED) + && !((media == U2F_MEDIA_USB) && (buffer[channelHeader] == U2F_CMD_INIT))) { // Unexpected continuation at this stage, abort u2f_transport_error(service, ERROR_INVALID_SEQ); goto error; @@ -366,56 +385,57 @@ void u2f_transport_received(u2f_service_t *service, uint8_t *buffer, } // Check if the command is supported switch (buffer[channelHeader]) { - case U2F_CMD_PING: - case U2F_CMD_MSG: + case U2F_CMD_PING: + case U2F_CMD_MSG: #ifdef HAVE_FIDO2 - case CTAP2_CMD_CBOR: - case CTAP2_CMD_CANCEL: + case CTAP2_CMD_CBOR: + case CTAP2_CMD_CANCEL: #endif - if (media == U2F_MEDIA_USB) { - if (u2f_is_channel_broadcast(service->channel) || - u2f_is_channel_forbidden(service->channel)) { + if (media == U2F_MEDIA_USB) { + if (u2f_is_channel_broadcast(service->channel) + || u2f_is_channel_forbidden(service->channel)) { + u2f_transport_error(service, ERROR_INVALID_CID); + goto error; + } + } + // no channel for BLE + break; + case U2F_CMD_INIT: + if (media != U2F_MEDIA_USB) { + // Unknown command, abort + u2f_transport_error(service, ERROR_INVALID_CMD); + goto error; + } + + if (u2f_is_channel_forbidden(service->channel)) { u2f_transport_error(service, ERROR_INVALID_CID); goto error; } - } - // no channel for BLE - break; - case U2F_CMD_INIT: - if (media != U2F_MEDIA_USB) { + + break; + default: // Unknown command, abort u2f_transport_error(service, ERROR_INVALID_CMD); goto error; - } - - if (u2f_is_channel_forbidden(service->channel)) { - u2f_transport_error(service, ERROR_INVALID_CID); - goto error; - } - - break; - default: - // Unknown command, abort - u2f_transport_error(service, ERROR_INVALID_CMD); - goto error; } // Ok, initialize the buffer - //if (buffer[channelHeader] != U2F_CMD_INIT) + // if (buffer[channelHeader] != U2F_CMD_INIT) { - xfer_len = MIN(size - (channelHeader), U2F_COMMAND_HEADER_SIZE+commandLength); + xfer_len = MIN(size - (channelHeader), U2F_COMMAND_HEADER_SIZE + commandLength); memmove(service->transportBuffer, buffer + channelHeader, xfer_len); if (media == U2F_MEDIA_USB) { service->commandCrc = cx_crc16_update(0, service->transportBuffer, xfer_len); } service->transportOffset = xfer_len; - service->transportLength = U2F_COMMAND_HEADER_SIZE+commandLength; - service->transportMedia = media; + service->transportLength = U2F_COMMAND_HEADER_SIZE + commandLength; + service->transportMedia = media; // initialize the response service->transportPacketIndex = 0; memcpy(service->transportChannel, service->channel, U2F_CHANNEL_ID_SIZE); } - } else { + } + else { // Continuation if (size < (channelHeader + 2)) { // Message to short, abort @@ -433,7 +453,8 @@ void u2f_transport_received(u2f_service_t *service, uint8_t *buffer, if (media == U2F_MEDIA_USB) { u2f_transport_reset(service); goto error; - } else { + } + else { u2f_transport_error(service, ERROR_INVALID_SEQ); goto error; } @@ -451,48 +472,55 @@ void u2f_transport_received(u2f_service_t *service, uint8_t *buffer, u2f_transport_error(service, ERROR_INVALID_SEQ); goto error; } - xfer_len = MIN(size - (channelHeader + 1), service->transportLength - service->transportOffset); - memmove(service->transportBuffer + service->transportOffset, buffer + channelHeader + 1, xfer_len); + xfer_len + = MIN(size - (channelHeader + 1), service->transportLength - service->transportOffset); + memmove(service->transportBuffer + service->transportOffset, + buffer + channelHeader + 1, + xfer_len); if (media == U2F_MEDIA_USB) { - service->commandCrc = cx_crc16_update(service->commandCrc, service->transportBuffer + service->transportOffset, xfer_len); + service->commandCrc = cx_crc16_update( + service->commandCrc, service->transportBuffer + service->transportOffset, xfer_len); } service->transportOffset += xfer_len; service->transportPacketIndex++; } // See if we can process the command - if ((media != U2F_MEDIA_USB) && - (service->transportOffset > - (service->transportLength + U2F_COMMAND_HEADER_SIZE))) { + if ((media != U2F_MEDIA_USB) + && (service->transportOffset > (service->transportLength + U2F_COMMAND_HEADER_SIZE))) { // Overflow, abort u2f_transport_error(service, ERROR_INVALID_LEN); goto error; - } else if (service->transportOffset >= service->transportLength) { + } + else if (service->transportOffset >= service->transportLength) { // switch before the handler gets the opportunity to change it again service->transportState = U2F_PROCESSING_COMMAND; // internal notification of a complete message received u2f_message_complete(service); - } else { + } + else { // new segment received, reset the timeout for the current piece - service->seqTimeout = 0; + service->seqTimeout = 0; service->transportState = U2F_HANDLE_SEGMENTED; } error: return; } -bool u2f_is_channel_broadcast(uint8_t *channel) { +bool u2f_is_channel_broadcast(uint8_t *channel) +{ return (memcmp(channel, BROADCAST_CHANNEL, 4) == 0); } -bool u2f_is_channel_forbidden(uint8_t *channel) { +bool u2f_is_channel_forbidden(uint8_t *channel) +{ return (memcmp(channel, FORBIDDEN_CHANNEL, 4) == 0); } /** * Auto reply hodl until the real reply is prepared and sent */ -void u2f_message_set_autoreply_wait_user_presence(u2f_service_t* service, bool enabled) { - +void u2f_message_set_autoreply_wait_user_presence(u2f_service_t *service, bool enabled) +{ // TODO : this only works for U2F if (enabled) { @@ -508,28 +536,27 @@ void u2f_message_set_autoreply_wait_user_presence(u2f_service_t* service, bool e } } -bool u2f_message_repliable(u2f_service_t* service) { +bool u2f_message_repliable(u2f_service_t *service) +{ // no more asynch replies // finished receiving the command // and not sending a user presence required status return service->waitAsynchronousResponse == U2F_WAIT_ASYNCH_IDLE - || (service->waitAsynchronousResponse != U2F_WAIT_ASYNCH_ON - && service->fakeChannelTransportState == U2F_FAKE_RECEIVED - && service->sending == false) - ; + || (service->waitAsynchronousResponse != U2F_WAIT_ASYNCH_ON + && service->fakeChannelTransportState == U2F_FAKE_RECEIVED + && service->sending == false); } -void u2f_message_reply(u2f_service_t *service, uint8_t cmd, uint8_t *buffer, uint16_t len) { - +void u2f_message_reply(u2f_service_t *service, uint8_t cmd, uint8_t *buffer, uint16_t len) +{ // if U2F is not ready to reply, then gently avoid replying - if (u2f_message_repliable(service)) - { - service->transportState = U2F_SENDING_RESPONSE; + if (u2f_message_repliable(service)) { + service->transportState = U2F_SENDING_RESPONSE; service->transportPacketIndex = 0; - service->transportBuffer = buffer; - service->transportOffset = 0; - service->transportLength = len; - service->sendCmd = cmd; + service->transportBuffer = buffer; + service->transportOffset = 0; + service->transportLength = len; + service->sendCmd = cmd; if (service->transportMedia != U2F_MEDIA_BLE) { // pump the first message u2f_transport_sent(service, service->transportMedia); @@ -542,5 +569,4 @@ void u2f_message_reply(u2f_service_t *service, uint8_t cmd, uint8_t *buffer, uin } } - #endif diff --git a/lib_ux/include/ux.h b/lib_ux/include/ux.h index 8dee61f87..c3edb907f 100644 --- a/lib_ux/include/ux.h +++ b/lib_ux/include/ux.h @@ -1,26 +1,26 @@ /******************************************************************************* -* Ledger Nano S - Secure firmware -* (c) 2022 Ledger -* -* Licensed under the Apache License, Version 2.0 (the "License"); -* you may not use this file except in compliance with the License. -* You may obtain a copy of the License at -* -* http://www.apache.org/licenses/LICENSE-2.0 -* -* Unless required by applicable law or agreed to in writing, software -* distributed under the License is distributed on an "AS IS" BASIS, -* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -* See the License for the specific language governing permissions and -* limitations under the License. -********************************************************************************/ + * Ledger Nano S - Secure firmware + * (c) 2022 Ledger + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + ********************************************************************************/ #pragma once #if defined(HAVE_BOLOS) -# include "bolos_privileged_ux.h" -#endif // HAVE_BOLOS +#include "bolos_privileged_ux.h" +#endif // HAVE_BOLOS #include "bolos_target.h" #include "lcx_ecfp.h" @@ -30,10 +30,10 @@ #ifndef HAVE_BOLOS_UX #ifndef HAVE_UX_FLOW - #define COMPLIANCE_UX_160 - #define HAVE_UX_LEGACY -#endif // HAVE_UX_FLOW -#endif // HAVE_BOLOS_UX +#define COMPLIANCE_UX_160 +#define HAVE_UX_LEGACY +#endif // HAVE_UX_FLOW +#endif // HAVE_BOLOS_UX #include "ux_layouts.h" #include "ux_flow_engine.h" @@ -42,7 +42,7 @@ #include "bolos_ux_loc_strings.h" #include "ux_loc_layouts.h" #include "ux_loc_flow_engine.h" -#endif //defined(HAVE_INDEXED_STRINGS) +#endif // defined(HAVE_INDEXED_STRINGS) #include "bagl.h" #include @@ -50,22 +50,22 @@ typedef struct bagl_element_e bagl_element_t; // callback returns NULL when element must not be redrawn (with a changing color or what so ever) -typedef const bagl_element_t* (*bagl_element_callback_t)(const bagl_element_t* element); +typedef const bagl_element_t *(*bagl_element_callback_t)(const bagl_element_t *element); // a graphic element is an element with defined text and actions depending on user touches struct bagl_element_e { - bagl_component_t component; + bagl_component_t component; #if defined(HAVE_INDEXED_STRINGS) - // Nameless union, to be able to access one member of the union or the other. - // No space won when using index with bagl_element_e, but headaches are avoided :) - union { - const char* text; - UX_LOC_STRINGS_INDEX index; - }; -#else //defined(HAVE_INDEXED_STRINGS) - const char* text; -#endif //defined(HAVE_INDEXED_STRINGS) + // Nameless union, to be able to access one member of the union or the other. + // No space won when using index with bagl_element_e, but headaches are avoided :) + union { + const char *text; + UX_LOC_STRINGS_INDEX index; + }; +#else // defined(HAVE_INDEXED_STRINGS) + const char *text; +#endif // defined(HAVE_INDEXED_STRINGS) }; // When not using indexed strings, some functions can be inlined, to save space @@ -75,89 +75,102 @@ struct bagl_element_e { #define STATIC_IF_NOT_INDEXED #endif -// touch management helper function (callback the call with the element for the given position, taking into account touch release) -void io_seproxyhal_touch(const bagl_element_t* elements, unsigned short element_count, unsigned short x, unsigned short y, unsigned char event_kind); -void io_seproxyhal_touch_element_callback(const bagl_element_t* elements, unsigned short element_count, unsigned short x, unsigned short y, unsigned char event_kind, bagl_element_callback_t before_display); +// touch management helper function (callback the call with the element for the given position, +// taking into account touch release) +void io_seproxyhal_touch(const bagl_element_t *elements, + unsigned short element_count, + unsigned short x, + unsigned short y, + unsigned char event_kind); +void io_seproxyhal_touch_element_callback(const bagl_element_t *elements, + unsigned short element_count, + unsigned short x, + unsigned short y, + unsigned char event_kind, + bagl_element_callback_t before_display); // callback to be implemented by the se -void io_seproxyhal_touch_callback(const bagl_element_t* element, unsigned char event); - +void io_seproxyhal_touch_callback(const bagl_element_t *element, unsigned char event); /** * Common strings prepro tosave space */ -const bagl_element_t* ux_layout_strings_prepro(const bagl_element_t* element); +const bagl_element_t *ux_layout_strings_prepro(const bagl_element_t *element); // meta type to share amongst all multiline layouts typedef struct ux_layout_strings_params_s { - const char* lines[5]; + const char *lines[5]; } ux_layout_strings_params_t; // meta type to share amongst all icon + multiline layouts typedef struct ux_layout_icon_strings_params_s { - const bagl_icon_details_t* icon; - const char* lines[5]; + const bagl_icon_details_t *icon; + const char *lines[5]; } ux_layout_icon_strings_params_t; #if defined(HAVE_INDEXED_STRINGS) -const bagl_element_t* ux_loc_layout_strings_prepro(const bagl_element_t* element); +const bagl_element_t *ux_loc_layout_strings_prepro(const bagl_element_t *element); // Prototypes related to localization const bagl_icon_details_t *get_glyphs_icon(unsigned char id); -const char *get_string_buffer(unsigned char id); -const char *get_ux_loc_string(UX_LOC_STRINGS_INDEX index); -#endif //defined(HAVE_INDEXED_STRINGS) +const char *get_string_buffer(unsigned char id); +const char *get_ux_loc_string(UX_LOC_STRINGS_INDEX index); +#endif // defined(HAVE_INDEXED_STRINGS) #if defined(HAVE_LANGUAGE_PACK) void bolos_ux_select_language(uint16_t language); void bolos_ux_refresh_language(void); typedef struct ux_loc_language_pack_infos { - unsigned char available; + unsigned char available; } UX_LOC_LANGUAGE_PACK_INFO; // To populate infos about language packs -SYSCALL PERMISSION(APPLICATION_FLAG_BOLOS_UX) void list_language_packs(UX_LOC_LANGUAGE_PACK_INFO *packs PLENGTH(NB_LANG*sizeof(UX_LOC_LANGUAGE_PACK_INFO))); -SYSCALL PERMISSION(APPLICATION_FLAG_BOLOS_UX) const LANGUAGE_PACK *get_language_pack(unsigned int language); -#endif //defined(HAVE_LANGUAGE_PACK) +SYSCALL PERMISSION(APPLICATION_FLAG_BOLOS_UX) void list_language_packs( + UX_LOC_LANGUAGE_PACK_INFO *packs PLENGTH(NB_LANG * sizeof(UX_LOC_LANGUAGE_PACK_INFO))); +SYSCALL PERMISSION(APPLICATION_FLAG_BOLOS_UX) const LANGUAGE_PACK *get_language_pack( + unsigned int language); +#endif // defined(HAVE_LANGUAGE_PACK) #ifndef BUTTON_FAST_THRESHOLD_CS -#define BUTTON_FAST_THRESHOLD_CS 8 //x100MS -#endif // BUTTON_FAST_THRESHOLD_CS +#define BUTTON_FAST_THRESHOLD_CS 8 // x100MS +#endif // BUTTON_FAST_THRESHOLD_CS #ifndef BUTTON_FAST_ACTION_CS -#define BUTTON_FAST_ACTION_CS 3 //x100MS -#endif // BUTTON_FAST_ACTION_CS +#define BUTTON_FAST_ACTION_CS 3 // x100MS +#endif // BUTTON_FAST_ACTION_CS -typedef unsigned int (*button_push_callback_t) (unsigned int button_mask, unsigned int button_mask_counter); -#define BUTTON_LEFT 1 -#define BUTTON_RIGHT 2 +typedef unsigned int (*button_push_callback_t)(unsigned int button_mask, + unsigned int button_mask_counter); +#define BUTTON_LEFT 1 +#define BUTTON_RIGHT 2 // flag set when fast threshold is reached and above -#define BUTTON_EVT_FAST 0x40000000UL -#define BUTTON_EVT_RELEASED 0x80000000UL -void io_seproxyhal_button_push(button_push_callback_t button_push_callback, unsigned int new_button_mask); - +#define BUTTON_EVT_FAST 0x40000000UL +#define BUTTON_EVT_RELEASED 0x80000000UL +void io_seproxyhal_button_push(button_push_callback_t button_push_callback, + unsigned int new_button_mask); // hal point (if application has to reprocess elements) void io_seproxyhal_display(const bagl_element_t *element); // Helper function that give a realistic timing of scrolling for label with text larger than screen -unsigned int bagl_label_roundtrip_duration_ms(const bagl_element_t* e, unsigned int average_char_width); -unsigned int bagl_label_roundtrip_duration_ms_buf(const bagl_element_t* e, const char* str, unsigned int average_char_width); +unsigned int bagl_label_roundtrip_duration_ms(const bagl_element_t *e, + unsigned int average_char_width); +unsigned int bagl_label_roundtrip_duration_ms_buf(const bagl_element_t *e, + const char *str, + unsigned int average_char_width); // default version to be called by ::io_seproxyhal_display if nothing to be done by the application -void io_seproxyhal_display_default(const bagl_element_t * element); - +void io_seproxyhal_display_default(const bagl_element_t *element); #ifndef UX_STACK_SLOT_COUNT #define UX_STACK_SLOT_COUNT 1 -#endif // UX_STACK_SLOT_COUNT +#endif // UX_STACK_SLOT_COUNT #ifndef UX_STACK_SLOT_ARRAY_COUNT #define UX_STACK_SLOT_ARRAY_COUNT 1 -#endif // UX_STACK_SLOT_ARRAY_COUNT - -typedef unsigned int (*callback_int_t) (unsigned int); -typedef void (*asynchmodal_end_callback_t) (unsigned int ux_status); +#endif // UX_STACK_SLOT_ARRAY_COUNT +typedef unsigned int (*callback_int_t)(unsigned int); +typedef void (*asynchmodal_end_callback_t)(unsigned int ux_status); typedef struct ux_stack_slot_s ux_stack_slot_t; @@ -167,7 +180,7 @@ typedef struct ux_stack_slot_s ux_stack_slot_t; typedef struct ux_state_s ux_state_t; // returns 0 if the element_array is not found, else stack_index + 1 if the element_array is found -unsigned int ux_stack_is_element_array_present(const bagl_element_t* element_array); +unsigned int ux_stack_is_element_array_present(const bagl_element_t *element_array); // push if a slot exists and returns the new slot, otherwise returns the top spot unsigned int ux_stack_push(void); @@ -176,7 +189,7 @@ unsigned int ux_stack_push(void); unsigned int ux_stack_pop(void); // inserts a new slot at the stack_slot -void ux_stack_insert(unsigned int stack_slot); // insert slot space as given index +void ux_stack_insert(unsigned int stack_slot); // insert slot space as given index // removes the slot at the stack_slot void ux_stack_remove(unsigned int stack_slot); @@ -186,22 +199,23 @@ void ux_stack_init(unsigned int stack_slot); // display the slot at index stack_slot void ux_stack_display(unsigned int stack_slot); -/** Function to be implemented by the UX manager (to allow specific callback and processing of the target) - * The next displayable element of the given stack slot must be displayed +/** Function to be implemented by the UX manager (to allow specific callback and processing of the + * target) The next displayable element of the given stack slot must be displayed */ void ux_stack_al_display_next_element(unsigned int stack_slot); // redisplay the top stacked slot. void ux_stack_redisplay(void); -const bagl_element_t* ux_stack_display_element_callback(const bagl_element_t* element); +const bagl_element_t *ux_stack_display_element_callback(const bagl_element_t *element); #ifdef HAVE_SE_SCREEN -void ux_stack_display_elements(ux_stack_slot_t* slot); -#endif // HAVE_SE_SCREEN +void ux_stack_display_elements(ux_stack_slot_t *slot); +#endif // HAVE_SE_SCREEN #ifdef HAVE_UX_LEGACY -// a menu callback is called with a given userid provided within the menu entry to allow for fast switch of the action to be taken -typedef void (*ux_menu_callback_t) (unsigned int userid); +// a menu callback is called with a given userid provided within the menu entry to allow for fast +// switch of the action to be taken +typedef void (*ux_menu_callback_t)(unsigned int userid); typedef struct ux_menu_entry_s ux_menu_entry_t; @@ -209,396 +223,455 @@ typedef struct ux_menu_entry_s ux_menu_entry_t; * Menu entry descriptor. */ struct ux_menu_entry_s { - // other menu shown when validated - const ux_menu_entry_t* menu; - // callback called when entered (not executed when a menu entry is present) - ux_menu_callback_t callback; - // user identifier to allow for indirection in a separated table and mutualise even more menu handling, passed to the given callback is any - unsigned int userid; - const bagl_icon_details_t* icon; - const char* line1; - const char* line2; - char text_x; - char icon_x; + // other menu shown when validated + const ux_menu_entry_t *menu; + // callback called when entered (not executed when a menu entry is present) + ux_menu_callback_t callback; + // user identifier to allow for indirection in a separated table and mutualise even more menu + // handling, passed to the given callback is any + unsigned int userid; + const bagl_icon_details_t *icon; + const char *line1; + const char *line2; + char text_x; + char icon_x; }; - -typedef const bagl_element_t* (*ux_menu_preprocessor_t) (const ux_menu_entry_t*, bagl_element_t* element); -typedef const ux_menu_entry_t* (*ux_menu_iterator_t) (unsigned int entry_idx); +typedef const bagl_element_t *(*ux_menu_preprocessor_t)(const ux_menu_entry_t *, + bagl_element_t *element); +typedef const ux_menu_entry_t *(*ux_menu_iterator_t)(unsigned int entry_idx); typedef struct ux_menu_state_s { - const ux_menu_entry_t* menu_entries; - unsigned int menu_entries_count; - unsigned int current_entry; - ux_menu_preprocessor_t menu_entry_preprocessor; - ux_menu_iterator_t menu_iterator; + const ux_menu_entry_t *menu_entries; + unsigned int menu_entries_count; + unsigned int current_entry; + ux_menu_preprocessor_t menu_entry_preprocessor; + ux_menu_iterator_t menu_iterator; } ux_menu_state_t; -// a menu callback is called with a given userid provided within the menu entry to allow for fast switch of the action to be taken -typedef void (*ux_turner_callback_t) (void); +// a menu callback is called with a given userid provided within the menu entry to allow for fast +// switch of the action to be taken +typedef void (*ux_turner_callback_t)(void); typedef struct ux_turner_step_s { - const bagl_icon_details_t* icon; - unsigned short fontid1; - const char* line1; - unsigned short fontid2; - const char* line2; - char text_x; - char icon_x; - unsigned int next_step_ms; + const bagl_icon_details_t *icon; + unsigned short fontid1; + const char *line1; + unsigned short fontid2; + const char *line2; + char text_x; + char icon_x; + unsigned int next_step_ms; } ux_turner_step_t; typedef struct ux_turner_state_s { - const ux_turner_step_t* steps; - unsigned int steps_count; - unsigned int current_step; - button_push_callback_t button_callback; - unsigned int elapsed_ms; + const ux_turner_step_t *steps; + unsigned int steps_count; + unsigned int current_step; + button_push_callback_t button_callback; + unsigned int elapsed_ms; } ux_turner_state_t; -#endif // HAVE_UX_LEGACY +#endif // HAVE_UX_LEGACY struct ux_stack_slot_s { // arrays of element to be displayed (to automate when dealing with static and dynamic elements) - bolos_task_status_t exit_code_after_elements_displayed; - unsigned char element_arrays_count; - unsigned short element_index; - // unsigned char displayed; - struct { - const bagl_element_t* element_array; - unsigned char element_array_count; - } element_arrays[UX_STACK_SLOT_ARRAY_COUNT]; + bolos_task_status_t exit_code_after_elements_displayed; + unsigned char element_arrays_count; + unsigned short element_index; + // unsigned char displayed; + struct { + const bagl_element_t *element_array; + unsigned char element_array_count; + } element_arrays[UX_STACK_SLOT_ARRAY_COUNT]; #if defined(HAVE_UX_FLOW) - callback_int_t displayed_callback; -#endif // defined(HAVE_UX_FLOW) - // callback called before the screen callback to change the keyboard face - bagl_element_callback_t screen_before_element_display_callback; - button_push_callback_t button_push_callback; - - callback_int_t ticker_callback; - unsigned int ticker_value; - unsigned int ticker_interval; + callback_int_t displayed_callback; +#endif // defined(HAVE_UX_FLOW) + // callback called before the screen callback to change the keyboard face + bagl_element_callback_t screen_before_element_display_callback; + button_push_callback_t button_push_callback; + + callback_int_t ticker_callback; + unsigned int ticker_value; + unsigned int ticker_interval; }; struct ux_state_s { - - unsigned char stack_count; // initialized @0 by the bolos ux initialize - bolos_task_status_t exit_code; + unsigned char stack_count; // initialized @0 by the bolos ux initialize + bolos_task_status_t exit_code; #ifdef HAVE_BLE - asynchmodal_end_callback_t asynchmodal_end_callback; -#endif // HAVE_BLE + asynchmodal_end_callback_t asynchmodal_end_callback; +#endif // HAVE_BLE #ifdef HAVE_UX_FLOW - // global context, therefore, don't allow for multiple paging overlaid in a graphic stack - ux_layout_paging_state_t layout_paging; + // global context, therefore, don't allow for multiple paging overlaid in a graphic stack + ux_layout_paging_state_t layout_paging; - // the flow for each stack slot - ux_flow_state_t flow_stack[UX_STACK_SLOT_COUNT]; + // the flow for each stack slot + ux_flow_state_t flow_stack[UX_STACK_SLOT_COUNT]; -#endif // HAVE_UX_FLOW +#endif // HAVE_UX_FLOW #if defined(HAVE_UX_FLOW) - // after an int to make sure it's aligned - char string_buffer[MAX(128,sizeof(bagl_icon_details_t)-1)]; -#endif // defined(HAVE_UX_FLOW) + // after an int to make sure it's aligned + char string_buffer[MAX(128, sizeof(bagl_icon_details_t) - 1)]; +#endif // defined(HAVE_UX_FLOW) - bagl_element_t tmp_element; + bagl_element_t tmp_element; - // unified arrays - // maxstack: [onboarding/dashboard/settings] | pairing | pin | batterylow | batterycrit | screensaver - ux_stack_slot_t stack[UX_STACK_SLOT_COUNT]; + // unified arrays + // maxstack: [onboarding/dashboard/settings] | pairing | pin | batterylow | batterycrit | + // screensaver + ux_stack_slot_t stack[UX_STACK_SLOT_COUNT]; #ifdef HAVE_UX_FLOW - // for menulist display - unsigned int menulist_current; - ux_layout_strings_params_t menulist_params; - list_item_value_t menulist_getter; - list_item_select_t menulist_selector; -#endif // HAVE_UX_FLOW + // for menulist display + unsigned int menulist_current; + ux_layout_strings_params_t menulist_params; + list_item_value_t menulist_getter; + list_item_select_t menulist_selector; +#endif // HAVE_UX_FLOW #ifdef COMPLIANCE_UX_160 - bolos_ux_params_t params; -#endif // COMPLIANCE_UX_160 + bolos_ux_params_t params; +#endif // COMPLIANCE_UX_160 - char *externalText; + char *externalText; }; #ifdef COMPLIANCE_UX_160 -#define G_ux ux -#define G_ux_params ux.params +#define G_ux ux +#define G_ux_params ux.params #define callback_interval_ms stack[0].ticker_interval -#define UX_INIT() \ - memset(&G_ux, 0, sizeof(G_ux)); \ - ux_stack_push(); +#define UX_INIT() \ + memset(&G_ux, 0, sizeof(G_ux)); \ + ux_stack_push(); extern ux_state_t G_ux; -#else // COMPLIANCE_UX_160 +#else // COMPLIANCE_UX_160 -extern ux_state_t G_ux; +extern ux_state_t G_ux; #if !defined(APP_UX) extern bolos_ux_params_t G_ux_params; -#endif // !defined(APP_UX) +#endif // !defined(APP_UX) /** * Initialize the user experience structure */ -#define UX_INIT() \ - memset(&G_ux, 0, sizeof(G_ux)); +#define UX_INIT() memset(&G_ux, 0, sizeof(G_ux)); -#endif // COMPLIANCE_UX_160 +#endif // COMPLIANCE_UX_160 /** * Request displaying the next element in the UX structure. * Take into account if a seproxyhal status has already been issued. - * Take into account if the next element is allowed/denied for display by the registered preprocessor + * Take into account if the next element is allowed/denied for display by the registered + * preprocessor */ #ifdef HAVE_SE_SCREEN -#define UX_DISPLAY_NEXT_ELEMENT() \ - if (G_ux.stack[0].element_arrays[0].element_array \ - && G_ux.stack[0].element_index < G_ux.stack[0].element_arrays[0].element_array_count \ - && (os_perso_isonboarded() != BOLOS_UX_OK || os_global_pin_is_validated() == BOLOS_UX_OK)) { \ - while (G_ux.stack[0].element_index < G_ux.stack[0].element_arrays[0].element_array_count) { \ - const bagl_element_t* element = &G_ux.stack[0].element_arrays[0].element_array[G_ux.stack[0].element_index]; \ - if (!G_ux.stack[0].screen_before_element_display_callback || (element = G_ux.stack[0].screen_before_element_display_callback(element)) ) { \ - if ((unsigned int)element == 1) { /*backward compat with coding to avoid smashing everything*/ \ - element = &G_ux.stack[0].element_arrays[0].element_array[G_ux.stack[0].element_index]; \ - } \ - io_seproxyhal_display(element); \ - } \ - G_ux.stack[0].element_index++; \ - } \ - if (G_ux.stack[0].element_index == G_ux.stack[0].element_arrays[0].element_array_count) { \ - screen_update(); \ - } \ - } -#else // HAVE_SE_SCREEN -#define UX_DISPLAY_NEXT_ELEMENT() \ - while (G_ux.stack[0].element_arrays[0].element_array \ - && G_ux.stack[0].element_index < G_ux.stack[0].element_arrays[0].element_array_count \ - && ! io_seproxyhal_spi_is_status_sent() \ - && (os_perso_isonboarded() != BOLOS_UX_OK || os_global_pin_is_validated() == BOLOS_UX_OK)) { \ - const bagl_element_t* element = &G_ux.stack[0].element_arrays[0].element_array[G_ux.stack[0].element_index]; \ - if (!G_ux.stack[0].screen_before_element_display_callback || (element = G_ux.stack[0].screen_before_element_display_callback(element)) ) { \ - if ((unsigned int)element == 1) { /*backward compat with coding to avoid smashing everything*/ \ - element = &G_ux.stack[0].element_arrays[0].element_array[G_ux.stack[0].element_index]; \ - } \ - io_seproxyhal_display(element); \ - } \ - G_ux.stack[0].element_index++; \ - } -#endif // HAVE_SE_SCREEN +#define UX_DISPLAY_NEXT_ELEMENT() \ + if (G_ux.stack[0].element_arrays[0].element_array \ + && G_ux.stack[0].element_index < G_ux.stack[0].element_arrays[0].element_array_count \ + && (os_perso_isonboarded() != BOLOS_UX_OK \ + || os_global_pin_is_validated() == BOLOS_UX_OK)) { \ + while (G_ux.stack[0].element_index \ + < G_ux.stack[0].element_arrays[0].element_array_count) { \ + const bagl_element_t *element \ + = &G_ux.stack[0].element_arrays[0].element_array[G_ux.stack[0].element_index]; \ + if (!G_ux.stack[0].screen_before_element_display_callback \ + || (element = G_ux.stack[0].screen_before_element_display_callback(element))) { \ + if ((unsigned int) element \ + == 1) { /*backward compat with coding to avoid smashing everything*/ \ + element = &G_ux.stack[0] \ + .element_arrays[0] \ + .element_array[G_ux.stack[0].element_index]; \ + } \ + io_seproxyhal_display(element); \ + } \ + G_ux.stack[0].element_index++; \ + } \ + if (G_ux.stack[0].element_index == G_ux.stack[0].element_arrays[0].element_array_count) { \ + screen_update(); \ + } \ + } +#else // HAVE_SE_SCREEN +#define UX_DISPLAY_NEXT_ELEMENT() \ + while (G_ux.stack[0].element_arrays[0].element_array \ + && G_ux.stack[0].element_index < G_ux.stack[0].element_arrays[0].element_array_count \ + && !io_seproxyhal_spi_is_status_sent() \ + && (os_perso_isonboarded() != BOLOS_UX_OK \ + || os_global_pin_is_validated() == BOLOS_UX_OK)) { \ + const bagl_element_t *element \ + = &G_ux.stack[0].element_arrays[0].element_array[G_ux.stack[0].element_index]; \ + if (!G_ux.stack[0].screen_before_element_display_callback \ + || (element = G_ux.stack[0].screen_before_element_display_callback(element))) { \ + if ((unsigned int) element \ + == 1) { /*backward compat with coding to avoid smashing everything*/ \ + element \ + = &G_ux.stack[0].element_arrays[0].element_array[G_ux.stack[0].element_index]; \ + } \ + io_seproxyhal_display(element); \ + } \ + G_ux.stack[0].element_index++; \ + } +#endif // HAVE_SE_SCREEN #ifdef HAVE_BLE /** - * internal bolos ux event processing with callback in case event is to be processed by the application + * internal bolos ux event processing with callback in case event is to be processed by the + * application */ -#define UX_FORWARD_EVENT_REDRAWCB(bypasspincheck, G_ux_params, G_ux, os_ux, os_sched_last_status, callback, redraw_cb, ignoring_app_if_ux_busy) \ - G_ux_params.ux_id = BOLOS_UX_EVENT; \ - G_ux_params.len = 0; \ - os_ux(&G_ux_params); \ - G_ux_params.len = os_sched_last_status(TASK_BOLOS_UX); \ - if (G_ux.asynchmodal_end_callback && os_ux_get_status(BOLOS_UX_ASYNCHMODAL_PAIRING_REQUEST) != 0) { asynchmodal_end_callback_t cb = G_ux.asynchmodal_end_callback; G_ux.asynchmodal_end_callback = NULL; cb(os_ux_get_status(BOLOS_UX_ASYNCHMODAL_PAIRING_REQUEST)) ; G_ux_params.len = BOLOS_UX_REDRAW; } \ - if (G_ux_params.len == BOLOS_UX_REDRAW) { \ - redraw_cb; \ - } \ - else if(!ignoring_app_if_ux_busy || (G_ux_params.len != BOLOS_UX_IGNORE && G_ux_params.len != BOLOS_UX_CONTINUE)) { \ - callback; \ - } - -#else // HAVE_BLE +#define UX_FORWARD_EVENT_REDRAWCB(bypasspincheck, \ + G_ux_params, \ + G_ux, \ + os_ux, \ + os_sched_last_status, \ + callback, \ + redraw_cb, \ + ignoring_app_if_ux_busy) \ + G_ux_params.ux_id = BOLOS_UX_EVENT; \ + G_ux_params.len = 0; \ + os_ux(&G_ux_params); \ + G_ux_params.len = os_sched_last_status(TASK_BOLOS_UX); \ + if (G_ux.asynchmodal_end_callback \ + && os_ux_get_status(BOLOS_UX_ASYNCHMODAL_PAIRING_REQUEST) != 0) { \ + asynchmodal_end_callback_t cb = G_ux.asynchmodal_end_callback; \ + G_ux.asynchmodal_end_callback = NULL; \ + cb(os_ux_get_status(BOLOS_UX_ASYNCHMODAL_PAIRING_REQUEST)); \ + G_ux_params.len = BOLOS_UX_REDRAW; \ + } \ + if (G_ux_params.len == BOLOS_UX_REDRAW) { \ + redraw_cb; \ + } \ + else if (!ignoring_app_if_ux_busy \ + || (G_ux_params.len != BOLOS_UX_IGNORE && G_ux_params.len != BOLOS_UX_CONTINUE)) { \ + callback; \ + } + +#else // HAVE_BLE /** - * internal bolos ux event processing with callback in case event is to be processed by the application + * internal bolos ux event processing with callback in case event is to be processed by the + * application */ -#define UX_FORWARD_EVENT_REDRAWCB(bypasspincheck, G_ux_params, G_ux, os_ux, os_sched_last_status, callback, redraw_cb, ignoring_app_if_ux_busy) \ - G_ux_params.ux_id = BOLOS_UX_EVENT; \ - G_ux_params.len = 0; \ - os_ux(&G_ux_params); \ - G_ux_params.len = os_sched_last_status(TASK_BOLOS_UX); \ - if (G_ux_params.len == BOLOS_UX_REDRAW) { \ - redraw_cb; \ - } \ - else if(!ignoring_app_if_ux_busy || (G_ux_params.len != BOLOS_UX_IGNORE && G_ux_params.len != BOLOS_UX_CONTINUE)) { \ - callback; \ - } -#endif // HAVE_BLE +#define UX_FORWARD_EVENT_REDRAWCB(bypasspincheck, \ + G_ux_params, \ + G_ux, \ + os_ux, \ + os_sched_last_status, \ + callback, \ + redraw_cb, \ + ignoring_app_if_ux_busy) \ + G_ux_params.ux_id = BOLOS_UX_EVENT; \ + G_ux_params.len = 0; \ + os_ux(&G_ux_params); \ + G_ux_params.len = os_sched_last_status(TASK_BOLOS_UX); \ + if (G_ux_params.len == BOLOS_UX_REDRAW) { \ + redraw_cb; \ + } \ + else if (!ignoring_app_if_ux_busy \ + || (G_ux_params.len != BOLOS_UX_IGNORE && G_ux_params.len != BOLOS_UX_CONTINUE)) { \ + callback; \ + } +#endif // HAVE_BLE /** - * Request a wake up of the device (backlight, pin lock screen, ...) to display a new interface to the user. - * Wake up prevent both autolock and power off features. Therefore, security wise, this function shall only - * be called to request direct user interaction. + * Request a wake up of the device (backlight, pin lock screen, ...) to display a new interface to + * the user. Wake up prevent both autolock and power off features. Therefore, security wise, this + * function shall only be called to request direct user interaction. */ -#define UX_WAKE_UP() \ - G_ux_params.ux_id = BOLOS_UX_WAKE_UP; \ - G_ux_params.len = 0; \ - os_ux(&G_ux_params); \ - G_ux_params.len = os_sched_last_status(TASK_BOLOS_UX); - +#define UX_WAKE_UP() \ + G_ux_params.ux_id = BOLOS_UX_WAKE_UP; \ + G_ux_params.len = 0; \ + os_ux(&G_ux_params); \ + G_ux_params.len = os_sched_last_status(TASK_BOLOS_UX); /** * Redisplay request (no immediate display status sent) */ -#define UX_REDISPLAY_REQUEST() \ - io_seproxyhal_init_ux(); \ - io_seproxyhal_init_button(); \ - G_ux.stack[0].element_index = 0; +#define UX_REDISPLAY_REQUEST() \ + io_seproxyhal_init_ux(); \ + io_seproxyhal_init_button(); \ + G_ux.stack[0].element_index = 0; /** * Force redisplay of the screen from the given index in the screen's element array */ -#define UX_REDISPLAY_IDX(index) \ - io_seproxyhal_init_ux(); \ - io_seproxyhal_init_button(); /*ensure to avoid release of a button from a nother screen to mess up with the redisplayed screen */ \ - G_ux.stack[0].element_index = index; \ - /* REDRAW is redisplay already, use os_ux return value to check */ \ - G_ux_params.len = os_sched_last_status(TASK_BOLOS_UX); \ - if (G_ux_params.len != BOLOS_UX_IGNORE && G_ux_params.len != BOLOS_UX_CONTINUE) { \ - UX_DISPLAY_NEXT_ELEMENT(); \ - } +#define UX_REDISPLAY_IDX(index) \ + io_seproxyhal_init_ux(); \ + io_seproxyhal_init_button(); /*ensure to avoid release of a button from a nother screen to \ + mess up with the redisplayed screen */ \ + G_ux.stack[0].element_index = index; \ + /* REDRAW is redisplay already, use os_ux return value to check */ \ + G_ux_params.len = os_sched_last_status(TASK_BOLOS_UX); \ + if (G_ux_params.len != BOLOS_UX_IGNORE && G_ux_params.len != BOLOS_UX_CONTINUE) { \ + UX_DISPLAY_NEXT_ELEMENT(); \ + } /** * Redisplay all elements of the screen */ -#define UX_REDISPLAY() \ - UX_REDISPLAY_IDX(0) +#define UX_REDISPLAY() UX_REDISPLAY_IDX(0) -#define UX_DISPLAY(elements_array, preprocessor) \ - G_ux.stack[0].element_arrays[0].element_array = elements_array; \ - G_ux.stack[0].element_arrays[0].element_array_count = sizeof(elements_array)/sizeof(elements_array[0]); \ - G_ux.stack[0].button_push_callback = elements_array ## _button; \ - G_ux.stack[0].screen_before_element_display_callback = preprocessor; \ - UX_WAKE_UP(); \ - UX_REDISPLAY(); +#define UX_DISPLAY(elements_array, preprocessor) \ + G_ux.stack[0].element_arrays[0].element_array = elements_array; \ + G_ux.stack[0].element_arrays[0].element_array_count \ + = sizeof(elements_array) / sizeof(elements_array[0]); \ + G_ux.stack[0].button_push_callback = elements_array##_button; \ + G_ux.stack[0].screen_before_element_display_callback = preprocessor; \ + UX_WAKE_UP(); \ + UX_REDISPLAY(); /** * Request the given UX to be redisplayed without emitting a display status right now (to continue * current operation, like transferring an USB reply) */ -#define UX_DISPLAY_REQUEST(elements_array, preprocessor) \ - G_ux.stack[0].element_arrays[0].element_array = elements_array; \ - G_ux.stack[0].element_arrays[0].element_array_count = sizeof(elements_array)/sizeof(elements_array[0]); \ - G_ux.stack[0].button_push_callback = elements_array ## _button; \ - G_ux.stack[0].screen_before_element_display_callback = preprocessor; \ - UX_WAKE_UP(); +#define UX_DISPLAY_REQUEST(elements_array, preprocessor) \ + G_ux.stack[0].element_arrays[0].element_array = elements_array; \ + G_ux.stack[0].element_arrays[0].element_array_count \ + = sizeof(elements_array) / sizeof(elements_array[0]); \ + G_ux.stack[0].button_push_callback = elements_array##_button; \ + G_ux.stack[0].screen_before_element_display_callback = preprocessor; \ + UX_WAKE_UP(); /** - * Request a screen redisplay after the given milliseconds interval has passed. Interval is not repeated, it's a single shot callback. must be re-enabled (the JS way). + * Request a screen redisplay after the given milliseconds interval has passed. Interval is not + * repeated, it's a single shot callback. must be re-enabled (the JS way). */ -#define UX_CALLBACK_SET_INTERVAL(ms) \ - G_ux.stack[0].ticker_value = ms; +#define UX_CALLBACK_SET_INTERVAL(ms) G_ux.stack[0].ticker_value = ms; /** - * internal bolos ux event processing with callback in case event is to be processed by the application + * internal bolos ux event processing with callback in case event is to be processed by the + * application */ -#define UX_FORWARD_EVENT(callback, ignoring_app_if_ux_busy) UX_FORWARD_EVENT_REDRAWCB(0, G_ux_params, G_io_asynch_ux_callback, os_ux, os_sched_last_status, callback, UX_REDISPLAY(), ignoring_app_if_ux_busy); - -#define UX_CONTINUE_DISPLAY_APP(displayed_callback) \ - UX_DISPLAY_NEXT_ELEMENT(); \ - /* all items have been displayed */ \ - if (G_ux.stack[0].element_index >= G_ux.stack[0].element_arrays[0].element_array_count && !io_seproxyhal_spi_is_status_sent()) { \ - displayed_callback \ +#define UX_FORWARD_EVENT(callback, ignoring_app_if_ux_busy) \ + UX_FORWARD_EVENT_REDRAWCB(0, \ + G_ux_params, \ + G_io_asynch_ux_callback, \ + os_ux, \ + os_sched_last_status, \ + callback, \ + UX_REDISPLAY(), \ + ignoring_app_if_ux_busy); + +#define UX_CONTINUE_DISPLAY_APP(displayed_callback) \ + UX_DISPLAY_NEXT_ELEMENT(); \ + /* all items have been displayed */ \ + if (G_ux.stack[0].element_index >= G_ux.stack[0].element_arrays[0].element_array_count \ + && !io_seproxyhal_spi_is_status_sent()) { \ + displayed_callback \ } /** * Process display processed event (by the os_ux or by the application code) */ #define UX_DISPLAYED_EVENT(displayed_callback) \ - UX_FORWARD_EVENT({ \ - UX_CONTINUE_DISPLAY_APP(displayed_callback); \ - }, 1) + UX_FORWARD_EVENT({ UX_CONTINUE_DISPLAY_APP(displayed_callback); }, 1) /** * Deprecated version to be removed */ -#define UX_DISPLAYED() (G_ux.stack[0].element_index >= G_ux.stack[0].element_arrays[0].element_array_count) - +#define UX_DISPLAYED() \ + (G_ux.stack[0].element_index >= G_ux.stack[0].element_arrays[0].element_array_count) /** - * Macro to process sequentially display a screen. The call finishes when the UX is completely displayed, - * and the state of the MCU <-> SE exchanges is the same as before this macro call. + * Macro to process sequentially display a screen. The call finishes when the UX is completely + * displayed, and the state of the MCU <-> SE exchanges is the same as before this macro call. */ -#define UX_WAIT_DISPLAYED() \ - while (!UX_DISPLAYED()) { \ - /* We wait for the MCU event (should indicate display processed for a bagl element) */ \ - io_seproxyhal_spi_recv(G_io_seproxyhal_spi_buffer, sizeof(G_io_seproxyhal_spi_buffer), 0); \ - io_seproxyhal_handle_event(); \ - UX_DISPLAY_NEXT_ELEMENT(); \ - } \ - io_seproxyhal_spi_recv(G_io_seproxyhal_spi_buffer, sizeof(G_io_seproxyhal_spi_buffer), 0); \ - io_seproxyhal_handle_event(); \ - /* We send a general status which indicates to the MCU that he can process any pending action (i.e. here, display the whole screen) */ \ - io_seproxyhal_general_status(); \ - /* We wait for an ack of the MCU. */ \ +#define UX_WAIT_DISPLAYED() \ + while (!UX_DISPLAYED()) { \ + /* We wait for the MCU event (should indicate display processed for a bagl element) */ \ + io_seproxyhal_spi_recv(G_io_seproxyhal_spi_buffer, sizeof(G_io_seproxyhal_spi_buffer), 0); \ + io_seproxyhal_handle_event(); \ + UX_DISPLAY_NEXT_ELEMENT(); \ + } \ + io_seproxyhal_spi_recv(G_io_seproxyhal_spi_buffer, sizeof(G_io_seproxyhal_spi_buffer), 0); \ + io_seproxyhal_handle_event(); \ + /* We send a general status which indicates to the MCU that he can process any pending action \ + * (i.e. here, display the whole screen) */ \ + io_seproxyhal_general_status(); \ + /* We wait for an ack of the MCU. */ \ io_seproxyhal_spi_recv(G_io_seproxyhal_spi_buffer, sizeof(G_io_seproxyhal_spi_buffer), 0); /** - * Process button push events. Application's button event handler is called only if the ux app does not deny it (modal frame displayed). + * Process button push events. Application's button event handler is called only if the ux app does + * not deny it (modal frame displayed). */ -#define UX_BUTTON_PUSH_EVENT(seph_packet) \ - UX_FORWARD_EVENT({ \ - if (G_ux.stack[0].button_push_callback) { \ - io_seproxyhal_button_push(G_ux.stack[0].button_push_callback, \ - seph_packet[3]>>1); \ - } \ - UX_CONTINUE_DISPLAY_APP({}); \ - }, 1); +#define UX_BUTTON_PUSH_EVENT(seph_packet) \ + UX_FORWARD_EVENT( \ + { \ + if (G_ux.stack[0].button_push_callback) { \ + io_seproxyhal_button_push(G_ux.stack[0].button_push_callback, \ + seph_packet[3] >> 1); \ + } \ + UX_CONTINUE_DISPLAY_APP({}); \ + }, \ + 1); #define UX_FINGER_EVENT(seph_packet) /** - * forward the ticker_event to the os ux handler. Ticker event callback is always called whatever the return code of the ux app. - * Ticker event interval is assumed to be 100 ms. + * forward the ticker_event to the os ux handler. Ticker event callback is always called whatever + * the return code of the ux app. Ticker event interval is assumed to be 100 ms. */ -#define UX_TICKER_EVENT(seph_packet, callback) \ - UX_FORWARD_EVENT({ \ - unsigned int UX_ALLOWED = (G_ux_params.len != BOLOS_UX_IGNORE && G_ux_params.len != BOLOS_UX_CONTINUE); \ - if (G_ux.stack[0].ticker_value) { \ - G_ux.stack[0].ticker_value -= MIN(G_ux.stack[0].ticker_value, 100); \ - if (!G_ux.stack[0].ticker_value) { \ - if (!G_ux.stack[0].ticker_callback) { \ - callback \ - } \ - else { \ - G_ux.stack[0].ticker_value = G_ux.stack[0].ticker_interval; \ - G_ux.stack[0].ticker_callback(0); \ - } \ - } \ - } \ - if (UX_ALLOWED) { \ - UX_CONTINUE_DISPLAY_APP({}); \ - } \ - }, 0); +#define UX_TICKER_EVENT(seph_packet, callback) \ + UX_FORWARD_EVENT( \ + { \ + unsigned int UX_ALLOWED \ + = (G_ux_params.len != BOLOS_UX_IGNORE && G_ux_params.len != BOLOS_UX_CONTINUE); \ + if (G_ux.stack[0].ticker_value) { \ + G_ux.stack[0].ticker_value -= MIN(G_ux.stack[0].ticker_value, 100); \ + if (!G_ux.stack[0].ticker_value) { \ + if (!G_ux.stack[0].ticker_callback) { \ + callback \ + } \ + else { \ + G_ux.stack[0].ticker_value = G_ux.stack[0].ticker_interval; \ + G_ux.stack[0].ticker_callback(0); \ + } \ + } \ + } \ + if (UX_ALLOWED) { \ + UX_CONTINUE_DISPLAY_APP({}); \ + } \ + }, \ + 0); /** - * Forward the event, ignoring the UX return code, the event must therefore be either not processed or processed with extreme care by the application afterwards + * Forward the event, ignoring the UX return code, the event must therefore be either not processed + * or processed with extreme care by the application afterwards */ -#define UX_DEFAULT_EVENT() \ - UX_FORWARD_EVENT({ \ - UX_CONTINUE_DISPLAY_APP({}); \ - }, 0); +#define UX_DEFAULT_EVENT() UX_FORWARD_EVENT({ UX_CONTINUE_DISPLAY_APP({}); }, 0); /** - * Start displaying the system keyboard input to allow. keyboard entry ends when any ux call returns with an OK status. + * Start displaying the system keyboard input to allow. keyboard entry ends when any ux call returns + * with an OK status. */ -#define UX_DISPLAY_KEYBOARD(callback) \ - G_ux_params.ux_id = BOLOS_UX_KEYBOARD; \ - G_ux_params.len = 0; \ - os_ux(&G_ux_params); \ - G_ux_params.len = os_sched_last_status(TASK_BOLOS_UX); - +#define UX_DISPLAY_KEYBOARD(callback) \ + G_ux_params.ux_id = BOLOS_UX_KEYBOARD; \ + G_ux_params.len = 0; \ + os_ux(&G_ux_params); \ + G_ux_params.len = os_sched_last_status(TASK_BOLOS_UX); /** - * Setup the TICKER_EVENT interval. Application shall not use this entry point as it's the main ticking source. Use the ::UX_SET_INTERVAL_MS instead. + * Setup the TICKER_EVENT interval. Application shall not use this entry point as it's the main + * ticking source. Use the ::UX_SET_INTERVAL_MS instead. */ void io_seproxyhal_setup_ticker(unsigned int interval_ms); void io_seproxyhal_request_mcu_status(void); /** - * Helper function to order the MCU to display the given bitmap with the given color index, a table of size: (1<7000) => use a u_int16_t; +- there are 197 countries in the world, so 1 byte might be enough to store language information, +unless we plan to integrate dialects (>7000) => use a u_int16_t; - we may store some CRC, to check language pack's integrity. */ -#endif //defined(HAVE_LANGUAGE_PACK) +#endif // defined(HAVE_LANGUAGE_PACK) diff --git a/lib_ux/include/ux_loc_flow_engine.h b/lib_ux/include/ux_loc_flow_engine.h index e1b753099..6b665893f 100644 --- a/lib_ux/include/ux_loc_flow_engine.h +++ b/lib_ux/include/ux_loc_flow_engine.h @@ -1,20 +1,20 @@ /******************************************************************************* -* Ledger Nano S - Secure firmware -* (c) 2022 Ledger -* -* Licensed under the Apache License, Version 2.0 (the "License"); -* you may not use this file except in compliance with the License. -* You may obtain a copy of the License at -* -* http://www.apache.org/licenses/LICENSE-2.0 -* -* Unless required by applicable law or agreed to in writing, software -* distributed under the License is distributed on an "AS IS" BASIS, -* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -* See the License for the specific language governing permissions and -* limitations under the License. -********************************************************************************/ + * Ledger Nano S - Secure firmware + * (c) 2022 Ledger + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + ********************************************************************************/ #pragma once @@ -24,110 +24,114 @@ /** * Define a flow step given both its error and validation flow. */ -#define UX_LOC_STEP_FLOWS(stepname, layoutkind, preinit, timeout_ms, validate_flow, error_flow, ...) \ - void stepname ##_init (unsigned int stack_slot) { \ - preinit; \ - ux_layout_ ## layoutkind ## _init(stack_slot); \ - ux_layout_set_timeout(stack_slot, timeout_ms); \ - } \ - const ux_loc_layout_ ## layoutkind ## _params_t stepname ##_val = __VA_ARGS__; \ - const ux_flow_step_t stepname = { \ - stepname ## _init, \ - & stepname ## _val, \ - validate_flow, \ - error_flow, \ - } +#define UX_LOC_STEP_FLOWS( \ + stepname, layoutkind, preinit, timeout_ms, validate_flow, error_flow, ...) \ + void stepname##_init(unsigned int stack_slot) \ + { \ + preinit; \ + ux_layout_##layoutkind##_init(stack_slot); \ + ux_layout_set_timeout(stack_slot, timeout_ms); \ + } \ + const ux_loc_layout_##layoutkind##_params_t stepname##_val = __VA_ARGS__; \ + const ux_flow_step_t stepname = { \ + stepname##_init, \ + &stepname##_val, \ + validate_flow, \ + error_flow, \ + } #define UX_LOC_STEP(stepname, layoutkind, preinit, timeout_ms, validate_cb, error_flow, ...) \ - UX_FLOW_CALL(stepname ## _validate, { validate_cb; }) \ - void stepname ##_init (unsigned int stack_slot) { \ - preinit; \ - ux_layout_ ## layoutkind ## _init(stack_slot); \ - ux_layout_set_timeout(stack_slot, timeout_ms); \ - } \ - const ux_loc_layout_ ## layoutkind ## _params_t stepname ##_val = __VA_ARGS__; \ - const ux_flow_step_t stepname = { \ - stepname ## _init, \ - & stepname ## _val, \ - stepname ## _validate, \ - error_flow, \ - } - + UX_FLOW_CALL(stepname##_validate, { validate_cb; }) \ + void stepname##_init(unsigned int stack_slot) \ + { \ + preinit; \ + ux_layout_##layoutkind##_init(stack_slot); \ + ux_layout_set_timeout(stack_slot, timeout_ms); \ + } \ + const ux_loc_layout_##layoutkind##_params_t stepname##_val = __VA_ARGS__; \ + const ux_flow_step_t stepname = { \ + stepname##_init, \ + &stepname##_val, \ + stepname##_validate, \ + error_flow, \ + } /** * Define a flow step with a validation callback */ -#define UX_LOC_STEP_CB(stepname, layoutkind, validate_cb, ...) \ - UX_FLOW_CALL(stepname ## _validate, { validate_cb; }) \ - const ux_loc_layout_ ## layoutkind ## _params_t stepname ##_val = __VA_ARGS__; \ - const ux_flow_step_t stepname = { \ - ux_layout_ ## layoutkind ## _init, \ - & stepname ## _val, \ - stepname ## _validate, \ - NULL, \ - } +#define UX_LOC_STEP_CB(stepname, layoutkind, validate_cb, ...) \ + UX_FLOW_CALL(stepname##_validate, { validate_cb; }) \ + const ux_loc_layout_##layoutkind##_params_t stepname##_val = __VA_ARGS__; \ + const ux_flow_step_t stepname = { \ + ux_layout_##layoutkind##_init, \ + &stepname##_val, \ + stepname##_validate, \ + NULL, \ + } // deprecated #define UX_LOC_FLOW_DEF_VALID UX_LOC_STEP_VALID // deprecated -#define UX_LOC_STEP_VALID UX_LOC_STEP_CB +#define UX_LOC_STEP_VALID UX_LOC_STEP_CB /** * Define a flow step with a validation flow and error flow */ #define UX_LOC_STEP_FLOWCB(stepname, layoutkind, validate_flow, error_flow, ...) \ - const ux_loc_layout_ ## layoutkind ## _params_t stepname ##_val = __VA_ARGS__; \ - const ux_flow_step_t stepname = { \ - ux_layout_ ## layoutkind ## _init, \ - & stepname ## _val, \ - validate_flow, \ - error_flow, \ - } + const ux_loc_layout_##layoutkind##_params_t stepname##_val = __VA_ARGS__; \ + const ux_flow_step_t stepname = { \ + ux_layout_##layoutkind##_init, \ + &stepname##_val, \ + validate_flow, \ + error_flow, \ + } /** * Define a flow step with a validation callback and a preinit function to * render data into shared variable before screen is displayed */ -#define UX_LOC_STEP_CB_INIT(stepname, layoutkind, preinit, validate_cb, ...) \ - UX_FLOW_CALL(stepname ## _validate, { validate_cb; }) \ - void stepname ##_init (unsigned int stack_slot) { \ - preinit; \ - ux_layout_ ## layoutkind ## _init(stack_slot); \ - } \ - const ux_loc_layout_ ## layoutkind ## _params_t stepname ##_val = __VA_ARGS__; \ - const ux_flow_step_t stepname = { \ - stepname ## _init, \ - & stepname ## _val, \ - stepname ## _validate, \ - NULL, \ - } +#define UX_LOC_STEP_CB_INIT(stepname, layoutkind, preinit, validate_cb, ...) \ + UX_FLOW_CALL(stepname##_validate, { validate_cb; }) \ + void stepname##_init(unsigned int stack_slot) \ + { \ + preinit; \ + ux_layout_##layoutkind##_init(stack_slot); \ + } \ + const ux_loc_layout_##layoutkind##_params_t stepname##_val = __VA_ARGS__; \ + const ux_flow_step_t stepname = { \ + stepname##_init, \ + &stepname##_val, \ + stepname##_validate, \ + NULL, \ + } /** * Define a flow step with autovalidation after a given timeout (in ms) */ #define UX_LOC_STEP_TIMEOUT(stepname, layoutkind, timeout_ms, validate_flow, ...) \ - void stepname ##_init (unsigned int stack_slot) { \ - ux_layout_ ## layoutkind ## _init(stack_slot); \ - ux_layout_set_timeout(stack_slot, timeout_ms); \ - } \ - const ux_loc_layout_ ## layoutkind ## _params_t stepname ##_val = __VA_ARGS__; \ - const ux_flow_step_t stepname = { \ - stepname ## _init, \ - & stepname ## _val, \ - validate_flow, \ - NULL, \ - } + void stepname##_init(unsigned int stack_slot) \ + { \ + ux_layout_##layoutkind##_init(stack_slot); \ + ux_layout_set_timeout(stack_slot, timeout_ms); \ + } \ + const ux_loc_layout_##layoutkind##_params_t stepname##_val = __VA_ARGS__; \ + const ux_flow_step_t stepname = { \ + stepname##_init, \ + &stepname##_val, \ + validate_flow, \ + NULL, \ + } /** * Define a simple flow step, given its name, layout and content. */ -#define UX_LOC_STEP_NOCB(stepname, layoutkind, ...) \ - const ux_loc_layout_ ## layoutkind ## _params_t stepname ##_val = __VA_ARGS__; \ - const ux_flow_step_t stepname = { \ - ux_layout_ ## layoutkind ## _init, \ - & stepname ## _val, \ - NULL, \ - NULL, \ - } +#define UX_LOC_STEP_NOCB(stepname, layoutkind, ...) \ + const ux_loc_layout_##layoutkind##_params_t stepname##_val = __VA_ARGS__; \ + const ux_flow_step_t stepname = { \ + ux_layout_##layoutkind##_init, \ + &stepname##_val, \ + NULL, \ + NULL, \ + } // deprecated #define UX_FLOW_DEF_NOCB UX_STEP_NOCB @@ -135,211 +139,222 @@ * A Step with variant data (which could be overwritten by a flow idplsayed * in an higher flow and therefore need to be recomputed when step is redisplayed) */ -#define UX_LOC_STEP_NOCB_INIT(stepname, layoutkind, preinit, ...) \ - void stepname ##_init (unsigned int stack_slot) { \ - preinit; \ - ux_layout_ ## layoutkind ## _init(stack_slot); \ - } \ - const ux_loc_layout_ ## layoutkind ## _params_t stepname ##_val = __VA_ARGS__; \ - const ux_flow_step_t stepname = { \ - stepname ## _init, \ - & stepname ## _val, \ - NULL, \ - NULL, \ - } +#define UX_LOC_STEP_NOCB_INIT(stepname, layoutkind, preinit, ...) \ + void stepname##_init(unsigned int stack_slot) \ + { \ + preinit; \ + ux_layout_##layoutkind##_init(stack_slot); \ + } \ + const ux_loc_layout_##layoutkind##_params_t stepname##_val = __VA_ARGS__; \ + const ux_flow_step_t stepname = { \ + stepname##_init, \ + &stepname##_val, \ + NULL, \ + NULL, \ + } /** * A Step with variant data (which could be overwritten by a flow idplsayed * in an higher flow and therefore need to be recomputed when step is redisplayed) */ -#define UX_LOC_STEP_NOCB_POSTINIT(stepname, layoutkind, postinit, ...) \ - void stepname ##_init (unsigned int stack_slot) { \ - ux_layout_ ## layoutkind ## _init(stack_slot); \ - postinit; \ - } \ - const ux_loc_layout_ ## layoutkind ## _params_t stepname ##_val = __VA_ARGS__; \ - const ux_flow_step_t stepname = { \ - stepname ## _init, \ - & stepname ## _val, \ - NULL, \ - NULL, \ - } +#define UX_LOC_STEP_NOCB_POSTINIT(stepname, layoutkind, postinit, ...) \ + void stepname##_init(unsigned int stack_slot) \ + { \ + ux_layout_##layoutkind##_init(stack_slot); \ + postinit; \ + } \ + const ux_loc_layout_##layoutkind##_params_t stepname##_val = __VA_ARGS__; \ + const ux_flow_step_t stepname = { \ + stepname##_init, \ + &stepname##_val, \ + NULL, \ + NULL, \ + } // Define a flow that will display several pages, using a specific formatting: // ie \b to switch Bold On/Off, \n to force a new line etc -#define UX_LOC_PAGES(stepname, index) \ - const ux_loc_layout_params_t stepname ##_val = {index}; \ - const ux_flow_step_t stepname = { \ - ux_layout_pages_init, \ - & stepname ## _val, \ - NULL, \ - NULL, \ - } +#define UX_LOC_PAGES(stepname, index) \ + const ux_loc_layout_params_t stepname##_val = {index}; \ + const ux_flow_step_t stepname = { \ + ux_layout_pages_init, \ + &stepname##_val, \ + NULL, \ + NULL, \ + } #define UX_LOC_PAGES_NOCB UX_LOC_PAGES -#define UX_LOC_PAGES_INIT(stepname, preinit, index) \ - void stepname ##_init (unsigned int stack_slot) { \ - preinit; \ - ux_layout_pages_init(stack_slot); \ - } \ - const ux_loc_layout_params_t stepname ##_val = {index}; \ - const ux_flow_step_t stepname = { \ - stepname ## _init, \ - & stepname ## _val, \ - NULL, \ - NULL, \ - } +#define UX_LOC_PAGES_INIT(stepname, preinit, index) \ + void stepname##_init(unsigned int stack_slot) \ + { \ + preinit; \ + ux_layout_pages_init(stack_slot); \ + } \ + const ux_loc_layout_params_t stepname##_val = {index}; \ + const ux_flow_step_t stepname = { \ + stepname##_init, \ + &stepname##_val, \ + NULL, \ + NULL, \ + } -#define UX_LOC_PAGES_INIT_ERROR(stepname, preinit, error, index) \ - void stepname ##_init (unsigned int stack_slot) { \ - preinit; \ - ux_layout_pages_init(stack_slot); \ - } \ - const ux_loc_layout_params_t stepname ##_val = {index}; \ - const ux_flow_step_t stepname = { \ - stepname ## _init, \ - & stepname ## _val, \ - NULL, \ - error, \ - } +#define UX_LOC_PAGES_INIT_ERROR(stepname, preinit, error, index) \ + void stepname##_init(unsigned int stack_slot) \ + { \ + preinit; \ + ux_layout_pages_init(stack_slot); \ + } \ + const ux_loc_layout_params_t stepname##_val = {index}; \ + const ux_flow_step_t stepname = { \ + stepname##_init, \ + &stepname##_val, \ + NULL, \ + error, \ + } -#define UX_LOC_PAGES_CB(stepname, validate_cb, index) \ - UX_FLOW_CALL(stepname ## _validate, { validate_cb; }) \ - const ux_loc_layout_params_t stepname ##_val = {index}; \ - const ux_flow_step_t stepname = { \ - ux_layout_pages_init, \ - & stepname ## _val, \ - stepname ## _validate, \ - NULL, \ - } +#define UX_LOC_PAGES_CB(stepname, validate_cb, index) \ + UX_FLOW_CALL(stepname##_validate, { validate_cb; }) \ + const ux_loc_layout_params_t stepname##_val = {index}; \ + const ux_flow_step_t stepname = { \ + ux_layout_pages_init, \ + &stepname##_val, \ + stepname##_validate, \ + NULL, \ + } #define UX_LOC_PAGES_VALID UX_LOC_PAGES_CB #define UX_LOC_PAGES_CB_INIT(stepname, preinit, validate_cb, index) \ - UX_FLOW_CALL(stepname ## _validate, { validate_cb; }) \ - void stepname ##_init (unsigned int stack_slot) { \ - preinit; \ - ux_layout_pages_init(stack_slot); \ - } \ - const ux_loc_layout_params_t stepname ##_val = {index}; \ - const ux_flow_step_t stepname = { \ - stepname ## _init, \ - & stepname ## _val, \ - stepname ## _validate, \ - NULL, \ - } + UX_FLOW_CALL(stepname##_validate, { validate_cb; }) \ + void stepname##_init(unsigned int stack_slot) \ + { \ + preinit; \ + ux_layout_pages_init(stack_slot); \ + } \ + const ux_loc_layout_params_t stepname##_val = {index}; \ + const ux_flow_step_t stepname = { \ + stepname##_init, \ + &stepname##_val, \ + stepname##_validate, \ + NULL, \ + } -#define UX_LOC_PAGES_POSTINIT(stepname, postinit, index) \ - void stepname ##_init (unsigned int stack_slot) { \ - ux_layout_pages_init(stack_slot); \ - postinit; \ - } \ - const ux_loc_layout_params_t stepname ##_val = {index}; \ - const ux_flow_step_t stepname = { \ - stepname ## _init, \ - & stepname ## _val, \ - NULL, \ - NULL, \ - } +#define UX_LOC_PAGES_POSTINIT(stepname, postinit, index) \ + void stepname##_init(unsigned int stack_slot) \ + { \ + ux_layout_pages_init(stack_slot); \ + postinit; \ + } \ + const ux_loc_layout_params_t stepname##_val = {index}; \ + const ux_flow_step_t stepname = { \ + stepname##_init, \ + &stepname##_val, \ + NULL, \ + NULL, \ + } -#define UX_LOC_PAGES_TIMEOUT(stepname, timeout_ms, validate_cb, index)\ - void stepname ##_init (unsigned int stack_slot) { \ - ux_layout_pages_init(stack_slot); \ - ux_layout_set_timeout(stack_slot, timeout_ms); \ - } \ - const ux_loc_layout_params_t stepname ##_val = {index}; \ - const ux_flow_step_t stepname = { \ - stepname ## _init, \ - & stepname ## _val, \ - validate_cb, \ - NULL, \ - } +#define UX_LOC_PAGES_TIMEOUT(stepname, timeout_ms, validate_cb, index) \ + void stepname##_init(unsigned int stack_slot) \ + { \ + ux_layout_pages_init(stack_slot); \ + ux_layout_set_timeout(stack_slot, timeout_ms); \ + } \ + const ux_loc_layout_params_t stepname##_val = {index}; \ + const ux_flow_step_t stepname = { \ + stepname##_init, \ + &stepname##_val, \ + validate_cb, \ + NULL, \ + } // Define a flow that will display several pages, using a specific formatting: // ie \b to switch Bold On/Off, \n to force a new line etc with a pager // The provided index will contain the title, and index+1 the remaining text -#define UX_LOC_PAGING(stepname, index) \ - const ux_loc_layout_params_t stepname ##_val = {index}; \ - const ux_flow_step_t stepname = { \ - ux_loc_layout_paging_init, \ - & stepname ## _val, \ - NULL, \ - NULL, \ - } +#define UX_LOC_PAGING(stepname, index) \ + const ux_loc_layout_params_t stepname##_val = {index}; \ + const ux_flow_step_t stepname = { \ + ux_loc_layout_paging_init, \ + &stepname##_val, \ + NULL, \ + NULL, \ + } // Define a flow that will display several pages, using a specific formatting: // ie \b to switch Bold On/Off, \n to force a new line etc -#define UX_PAGES(stepname, text) \ - const ux_layout_pages_params_t stepname ##_val = {text}; \ - const ux_flow_step_t stepname = { \ - ux_layout_pages_init, \ - & stepname ## _val, \ - NULL, \ - NULL, \ - } +#define UX_PAGES(stepname, text) \ + const ux_layout_pages_params_t stepname##_val = {text}; \ + const ux_flow_step_t stepname = { \ + ux_layout_pages_init, \ + &stepname##_val, \ + NULL, \ + NULL, \ + } -#define UX_PAGES_INIT(stepname, preinit, text) \ - void stepname ##_init (unsigned int stack_slot) { \ - preinit; \ - ux_layout_pages_init(stack_slot); \ - } \ - const ux_layout_pages_params_t stepname ##_val = {text}; \ - const ux_flow_step_t stepname = { \ - stepname ## _init, \ - & stepname ## _val, \ - NULL, \ - NULL, \ - } +#define UX_PAGES_INIT(stepname, preinit, text) \ + void stepname##_init(unsigned int stack_slot) \ + { \ + preinit; \ + ux_layout_pages_init(stack_slot); \ + } \ + const ux_layout_pages_params_t stepname##_val = {text}; \ + const ux_flow_step_t stepname = { \ + stepname##_init, \ + &stepname##_val, \ + NULL, \ + NULL, \ + } -#define UX_PAGES_CB(stepname, validate_cb, text) \ - UX_FLOW_CALL(stepname ## _validate, { validate_cb; }) \ - const ux_layout_pages_params_t stepname ##_val = {text}; \ - const ux_flow_step_t stepname = { \ - ux_layout_pages_init, \ - & stepname ## _val, \ - stepname ## _validate, \ - NULL, \ - } +#define UX_PAGES_CB(stepname, validate_cb, text) \ + UX_FLOW_CALL(stepname##_validate, { validate_cb; }) \ + const ux_layout_pages_params_t stepname##_val = {text}; \ + const ux_flow_step_t stepname = { \ + ux_layout_pages_init, \ + &stepname##_val, \ + stepname##_validate, \ + NULL, \ + } -#define UX_PAGES_CB_INIT(stepname, preinit, validate_cb, text) \ - UX_FLOW_CALL(stepname ## _validate, { validate_cb; }) \ - void stepname ##_init (unsigned int stack_slot) { \ - preinit; \ - ux_layout_pages_init(stack_slot); \ - } \ - const ux_layout_pages_params_t stepname ##_val = {text}; \ - const ux_flow_step_t stepname = { \ - stepname ## _init, \ - & stepname ## _val, \ - stepname ## _validate, \ - NULL, \ - } +#define UX_PAGES_CB_INIT(stepname, preinit, validate_cb, text) \ + UX_FLOW_CALL(stepname##_validate, { validate_cb; }) \ + void stepname##_init(unsigned int stack_slot) \ + { \ + preinit; \ + ux_layout_pages_init(stack_slot); \ + } \ + const ux_layout_pages_params_t stepname##_val = {text}; \ + const ux_flow_step_t stepname = { \ + stepname##_init, \ + &stepname##_val, \ + stepname##_validate, \ + NULL, \ + } -#define UX_PAGES_POSTINIT(stepname, postinit, text) \ - void stepname ##_init (unsigned int stack_slot) { \ - ux_layout_pages_init(stack_slot); \ - postinit; \ - } \ - const ux_layout_pages_params_t stepname ##_val = {text}; \ - const ux_flow_step_t stepname = { \ - stepname ## _init, \ - & stepname ## _val, \ - NULL, \ - NULL, \ - } +#define UX_PAGES_POSTINIT(stepname, postinit, text) \ + void stepname##_init(unsigned int stack_slot) \ + { \ + ux_layout_pages_init(stack_slot); \ + postinit; \ + } \ + const ux_layout_pages_params_t stepname##_val = {text}; \ + const ux_flow_step_t stepname = { \ + stepname##_init, \ + &stepname##_val, \ + NULL, \ + NULL, \ + } -#define UX_PAGES_TIMEOUT(stepname, timeout_ms, validate_cb, text) \ - void stepname ##_init (unsigned int stack_slot) { \ - ux_layout_pages_init(stack_slot); \ - ux_layout_set_timeout(stack_slot, timeout_ms); \ - } \ - const ux_layout_pages_params_t stepname ##_val = {text}; \ - const ux_flow_step_t stepname = { \ - stepname ## _init, \ - & stepname ## _val, \ - validate_cb, \ - NULL, \ - } +#define UX_PAGES_TIMEOUT(stepname, timeout_ms, validate_cb, text) \ + void stepname##_init(unsigned int stack_slot) \ + { \ + ux_layout_pages_init(stack_slot); \ + ux_layout_set_timeout(stack_slot, timeout_ms); \ + } \ + const ux_layout_pages_params_t stepname##_val = {text}; \ + const ux_flow_step_t stepname = { \ + stepname##_init, \ + &stepname##_val, \ + validate_cb, \ + NULL, \ + } #define UX_PAGES_NOCB UX_PAGES diff --git a/lib_ux/include/ux_loc_layouts.h b/lib_ux/include/ux_loc_layouts.h index 727d7a64b..cbd5e897c 100644 --- a/lib_ux/include/ux_loc_layouts.h +++ b/lib_ux/include/ux_loc_layouts.h @@ -1,20 +1,20 @@ /******************************************************************************* -* Ledger Nano S - Secure firmware -* (c) 2022 Ledger -* -* Licensed under the Apache License, Version 2.0 (the "License"); -* you may not use this file except in compliance with the License. -* You may obtain a copy of the License at -* -* http://www.apache.org/licenses/LICENSE-2.0 -* -* Unless required by applicable law or agreed to in writing, software -* distributed under the License is distributed on an "AS IS" BASIS, -* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -* See the License for the specific language governing permissions and -* limitations under the License. -********************************************************************************/ + * Ledger Nano S - Secure firmware + * (c) 2022 Ledger + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + ********************************************************************************/ #pragma once #include "bolos_target.h" @@ -26,40 +26,40 @@ typedef BOLOS_UX_LOC_STRINGS UX_LOC_STRINGS_INDEX; //******************************************************************************** typedef struct ux_loc_layout_params_s { - const UX_LOC_STRINGS_INDEX index; + const UX_LOC_STRINGS_INDEX index; } ux_loc_layout_params_t; -#define ux_loc_layout_nn_paging_params_t ux_loc_layout_params_t -#define ux_loc_layout_nb_paging_params_t ux_loc_layout_params_t -#define ux_loc_layout_bn_paging_params_t ux_loc_layout_params_t -#define ux_loc_layout_bb_paging_params_t ux_loc_layout_params_t -#define ux_loc_layout_nnn_params_t ux_loc_layout_params_t -#define ux_loc_layout_bnn_params_t ux_loc_layout_params_t -#define ux_loc_layout_nnnn_params_t ux_loc_layout_params_t -#define ux_loc_layout_bnnn_params_t ux_loc_layout_params_t -#define ux_loc_layout_nnbnn_params_t ux_loc_layout_params_t -#define ux_loc_layout_pages_params_t ux_loc_layout_params_t +#define ux_loc_layout_nn_paging_params_t ux_loc_layout_params_t +#define ux_loc_layout_nb_paging_params_t ux_loc_layout_params_t +#define ux_loc_layout_bn_paging_params_t ux_loc_layout_params_t +#define ux_loc_layout_bb_paging_params_t ux_loc_layout_params_t +#define ux_loc_layout_nnn_params_t ux_loc_layout_params_t +#define ux_loc_layout_bnn_params_t ux_loc_layout_params_t +#define ux_loc_layout_nnnn_params_t ux_loc_layout_params_t +#define ux_loc_layout_bnnn_params_t ux_loc_layout_params_t +#define ux_loc_layout_nnbnn_params_t ux_loc_layout_params_t +#define ux_loc_layout_pages_params_t ux_loc_layout_params_t typedef struct ux_loc_layout_icon_params_s { - const bagl_icon_details_t* icon; - const UX_LOC_STRINGS_INDEX index; + const bagl_icon_details_t *icon; + const UX_LOC_STRINGS_INDEX index; } ux_loc_layout_icon_params_t; -#define ux_loc_layout_pb_params_t ux_loc_layout_icon_params_t -#define ux_loc_layout_pn_params_t ux_loc_layout_icon_params_t -#define ux_loc_layout_pbb_params_t ux_loc_layout_icon_params_t -#define ux_loc_layout_pnn_params_t ux_loc_layout_icon_params_t -#define ux_loc_layout_pbn_params_t ux_loc_layout_icon_params_t +#define ux_loc_layout_pb_params_t ux_loc_layout_icon_params_t +#define ux_loc_layout_pn_params_t ux_loc_layout_icon_params_t +#define ux_loc_layout_pbb_params_t ux_loc_layout_icon_params_t +#define ux_loc_layout_pnn_params_t ux_loc_layout_icon_params_t +#define ux_loc_layout_pbn_params_t ux_loc_layout_icon_params_t //******************************************************************************** typedef struct ux_layout_pages_params_s { - const char *text; + const char *text; } ux_layout_pages_params_t; -#if (BAGL_WIDTH==128 && BAGL_HEIGHT==64) - #define UX_LAYOUT_PAGES_LINE_COUNT 4 -#elif (BAGL_WIDTH==128 && BAGL_HEIGHT==32) - #define UX_LAYOUT_PAGES_LINE_COUNT 2 +#if (BAGL_WIDTH == 128 && BAGL_HEIGHT == 64) +#define UX_LAYOUT_PAGES_LINE_COUNT 4 +#elif (BAGL_WIDTH == 128 && BAGL_HEIGHT == 32) +#define UX_LAYOUT_PAGES_LINE_COUNT 2 #else #error "BAGL_WIDTH/BAGL_HEIGHT not defined" #endif @@ -69,6 +69,6 @@ void ux_loc_layout_pages_init(unsigned int stack_slot); void ux_loc_layout_paging_init(unsigned int stack_slot); // deprecation -#define ux_loc_layout_bnnn_paging_init ux_loc_layout_bn_paging_init -#define ux_loc_layout_bnnn_paging_reset ux_layout_paging_reset -#define ux_loc_layout_bn_paging_reset ux_layout_paging_reset +#define ux_loc_layout_bnnn_paging_init ux_loc_layout_bn_paging_init +#define ux_loc_layout_bnnn_paging_reset ux_layout_paging_reset +#define ux_loc_layout_bn_paging_reset ux_layout_paging_reset diff --git a/lib_ux/src/ux_flow_engine.c b/lib_ux/src/ux_flow_engine.c index aa33a2ea9..73f6d7502 100644 --- a/lib_ux/src/ux_flow_engine.c +++ b/lib_ux/src/ux_flow_engine.c @@ -1,20 +1,20 @@ /******************************************************************************* -* Ledger Nano S - Secure firmware -* (c) 2022 Ledger -* -* Licensed under the Apache License, Version 2.0 (the "License"); -* you may not use this file except in compliance with the License. -* You may obtain a copy of the License at -* -* http://www.apache.org/licenses/LICENSE-2.0 -* -* Unless required by applicable law or agreed to in writing, software -* distributed under the License is distributed on an "AS IS" BASIS, -* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -* See the License for the specific language governing permissions and -* limitations under the License. -********************************************************************************/ + * Ledger Nano S - Secure firmware + * (c) 2022 Ledger + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT 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 "ux.h" #include "os_helpers.h" @@ -26,340 +26,394 @@ #ifdef HAVE_UX_FLOW // check if flow is valid (has valid length and in correct stack slot) -static unsigned int ux_flow_check_valid(void) { - unsigned int top_stack_slot = G_ux.stack_count - 1; - - if (G_ux.stack_count > UX_STACK_SLOT_COUNT - || G_ux.flow_stack[top_stack_slot].length == 0) { - return 0; - } - return 1; -} +static unsigned int ux_flow_check_valid(void) +{ + unsigned int top_stack_slot = G_ux.stack_count - 1; -// to hide the left tick or not -unsigned int ux_flow_is_first(void) { - // no previous ? - unsigned int top_stack_slot = G_ux.stack_count - 1; - if (!ux_flow_check_valid() || G_ux.flow_stack[top_stack_slot].steps == NULL || - (G_ux.flow_stack[top_stack_slot].index == 0 && - G_ux.flow_stack[top_stack_slot].steps[G_ux.flow_stack[top_stack_slot].length - 1] != FLOW_LOOP)) { + if (G_ux.stack_count > UX_STACK_SLOT_COUNT || G_ux.flow_stack[top_stack_slot].length == 0) { + return 0; + } return 1; - } - - // previous is a flow barrier ? - if (G_ux.flow_stack[top_stack_slot].length > 0 && - G_ux.flow_stack[top_stack_slot].index < G_ux.flow_stack[top_stack_slot].length && - G_ux.flow_stack[top_stack_slot].steps[G_ux.flow_stack[top_stack_slot].index - 1] == FLOW_BARRIER) { - return 1; - } - - // not the first, for sure - return 0; } -unsigned int ux_flow_is_last(void){ - // last ? - unsigned int top_stack_slot = G_ux.stack_count - 1; - - if (!ux_flow_check_valid() - || G_ux.flow_stack[top_stack_slot].steps == NULL - || G_ux.flow_stack[top_stack_slot].length == 0 - || G_ux.flow_stack[top_stack_slot].index >= G_ux.flow_stack[top_stack_slot].length -1) { - return 1; - } - - // followed by a flow barrier ? - if (G_ux.flow_stack[top_stack_slot].length > 0 - && G_ux.flow_stack[top_stack_slot].index < G_ux.flow_stack[top_stack_slot].length - 2 - && G_ux.flow_stack[top_stack_slot].steps[G_ux.flow_stack[top_stack_slot].index+1] == FLOW_BARRIER) { - return 1; - } - - // is not last - return 0; +// to hide the left tick or not +unsigned int ux_flow_is_first(void) +{ + // no previous ? + unsigned int top_stack_slot = G_ux.stack_count - 1; + if (!ux_flow_check_valid() || G_ux.flow_stack[top_stack_slot].steps == NULL + || (G_ux.flow_stack[top_stack_slot].index == 0 + && G_ux.flow_stack[top_stack_slot].steps[G_ux.flow_stack[top_stack_slot].length - 1] + != FLOW_LOOP)) { + return 1; + } + + // previous is a flow barrier ? + if (G_ux.flow_stack[top_stack_slot].length > 0 + && G_ux.flow_stack[top_stack_slot].index < G_ux.flow_stack[top_stack_slot].length + && G_ux.flow_stack[top_stack_slot].steps[G_ux.flow_stack[top_stack_slot].index - 1] + == FLOW_BARRIER) { + return 1; + } + + // not the first, for sure + return 0; } -ux_flow_direction_t ux_flow_direction(void) { - unsigned int top_stack_slot = G_ux.stack_count - 1; - - if (G_ux.stack_count) { - if (G_ux.flow_stack[top_stack_slot].index > G_ux.flow_stack[top_stack_slot].prev_index) { - return FLOW_DIRECTION_FORWARD; - } - else if (G_ux.flow_stack[top_stack_slot].index < G_ux.flow_stack[top_stack_slot].prev_index) { - return FLOW_DIRECTION_BACKWARD; - } - } - return FLOW_DIRECTION_START; +unsigned int ux_flow_is_last(void) +{ + // last ? + unsigned int top_stack_slot = G_ux.stack_count - 1; + + if (!ux_flow_check_valid() || G_ux.flow_stack[top_stack_slot].steps == NULL + || G_ux.flow_stack[top_stack_slot].length == 0 + || G_ux.flow_stack[top_stack_slot].index >= G_ux.flow_stack[top_stack_slot].length - 1) { + return 1; + } + + // followed by a flow barrier ? + if (G_ux.flow_stack[top_stack_slot].length > 0 + && G_ux.flow_stack[top_stack_slot].index < G_ux.flow_stack[top_stack_slot].length - 2 + && G_ux.flow_stack[top_stack_slot].steps[G_ux.flow_stack[top_stack_slot].index + 1] + == FLOW_BARRIER) { + return 1; + } + + // is not last + return 0; } -const ux_flow_step_t* ux_flow_get_current(void) { - unsigned int top_stack_slot = G_ux.stack_count - 1; - - if (!ux_flow_check_valid() - || G_ux.flow_stack[top_stack_slot].steps == NULL - || G_ux.flow_stack[top_stack_slot].index >= G_ux.flow_stack[top_stack_slot].length - || G_ux.flow_stack[top_stack_slot].steps[G_ux.flow_stack[top_stack_slot].index] == FLOW_BARRIER - || G_ux.flow_stack[top_stack_slot].steps[G_ux.flow_stack[top_stack_slot].index] == FLOW_LOOP - || G_ux.flow_stack[top_stack_slot].steps[G_ux.flow_stack[top_stack_slot].index] == FLOW_END_STEP) { - return NULL; - } - return STEPPIC(G_ux.flow_stack[top_stack_slot].steps[G_ux.flow_stack[top_stack_slot].index]); +ux_flow_direction_t ux_flow_direction(void) +{ + unsigned int top_stack_slot = G_ux.stack_count - 1; + + if (G_ux.stack_count) { + if (G_ux.flow_stack[top_stack_slot].index > G_ux.flow_stack[top_stack_slot].prev_index) { + return FLOW_DIRECTION_FORWARD; + } + else if (G_ux.flow_stack[top_stack_slot].index + < G_ux.flow_stack[top_stack_slot].prev_index) { + return FLOW_DIRECTION_BACKWARD; + } + } + return FLOW_DIRECTION_START; } -static void ux_flow_engine_init_step(unsigned int stack_slot) { - // invalid ux_flow_length ??? (previous check shall have exited earlier) - if (G_ux.flow_stack[stack_slot].steps[G_ux.flow_stack[stack_slot].index] == FLOW_END_STEP) { - return; - } - // this shall not have occurred due to previous checks - if (G_ux.flow_stack[stack_slot].steps[G_ux.flow_stack[stack_slot].index] == FLOW_BARRIER) { - return; - } - // this shall not have occurred due to previous checks - if (G_ux.flow_stack[stack_slot].steps[G_ux.flow_stack[stack_slot].index] == FLOW_LOOP) { - return; - } - // if init function is set, call it - if (STEPPIC(G_ux.flow_stack[stack_slot].steps[G_ux.flow_stack[stack_slot].index])->init) { - INITPIC(STEPPIC(G_ux.flow_stack[stack_slot].steps[G_ux.flow_stack[stack_slot].index])->init)(stack_slot); - } - else { - // if init method is not set, jump to referenced flow and step - ux_flow_init(stack_slot, - STEPSPIC(STEPPIC(G_ux.flow_stack[stack_slot].steps[G_ux.flow_stack[stack_slot].index])->validate_flow), - (const ux_flow_step_t*) PIC(STEPPIC(G_ux.flow_stack[stack_slot].steps[G_ux.flow_stack[stack_slot].index])->params)); - } +const ux_flow_step_t *ux_flow_get_current(void) +{ + unsigned int top_stack_slot = G_ux.stack_count - 1; + + if (!ux_flow_check_valid() || G_ux.flow_stack[top_stack_slot].steps == NULL + || G_ux.flow_stack[top_stack_slot].index >= G_ux.flow_stack[top_stack_slot].length + || G_ux.flow_stack[top_stack_slot].steps[G_ux.flow_stack[top_stack_slot].index] + == FLOW_BARRIER + || G_ux.flow_stack[top_stack_slot].steps[G_ux.flow_stack[top_stack_slot].index] == FLOW_LOOP + || G_ux.flow_stack[top_stack_slot].steps[G_ux.flow_stack[top_stack_slot].index] + == FLOW_END_STEP) { + return NULL; + } + return STEPPIC(G_ux.flow_stack[top_stack_slot].steps[G_ux.flow_stack[top_stack_slot].index]); } -static void ux_flow_next_internal(unsigned int display_step) { - unsigned int top_stack_slot = G_ux.stack_count - 1; - - // last reached already (need validation, not next) - if (!ux_flow_check_valid() - || G_ux.flow_stack[top_stack_slot].steps == NULL - || G_ux.flow_stack[top_stack_slot].length <= 1 - || G_ux.flow_stack[top_stack_slot].index >= G_ux.flow_stack[top_stack_slot].length -1) { - return; - } - - // followed by a flow barrier ? => need validation instead of next - if (G_ux.flow_stack[top_stack_slot].index <= G_ux.flow_stack[top_stack_slot].length - 2) { - if (G_ux.flow_stack[top_stack_slot].steps[G_ux.flow_stack[top_stack_slot].index+1] == FLOW_BARRIER) { - return; - } - - // followed by a flow barrier ? => need validation instead of next - if (G_ux.flow_stack[top_stack_slot].steps[G_ux.flow_stack[top_stack_slot].index+1] == FLOW_LOOP) { - // display first step, fake direction as forward - G_ux.flow_stack[top_stack_slot].prev_index = G_ux.flow_stack[top_stack_slot].index = 0; - ux_flow_engine_init_step(top_stack_slot); - return; - } - } - - // advance flow pointer and display it (skip META STEPS) - G_ux.flow_stack[top_stack_slot].prev_index = G_ux.flow_stack[top_stack_slot].index; - G_ux.flow_stack[top_stack_slot].index++; - if (display_step) { - ux_flow_engine_init_step(top_stack_slot); - } +static void ux_flow_engine_init_step(unsigned int stack_slot) +{ + // invalid ux_flow_length ??? (previous check shall have exited earlier) + if (G_ux.flow_stack[stack_slot].steps[G_ux.flow_stack[stack_slot].index] == FLOW_END_STEP) { + return; + } + // this shall not have occurred due to previous checks + if (G_ux.flow_stack[stack_slot].steps[G_ux.flow_stack[stack_slot].index] == FLOW_BARRIER) { + return; + } + // this shall not have occurred due to previous checks + if (G_ux.flow_stack[stack_slot].steps[G_ux.flow_stack[stack_slot].index] == FLOW_LOOP) { + return; + } + // if init function is set, call it + if (STEPPIC(G_ux.flow_stack[stack_slot].steps[G_ux.flow_stack[stack_slot].index])->init) { + INITPIC(STEPPIC(G_ux.flow_stack[stack_slot].steps[G_ux.flow_stack[stack_slot].index])->init) + (stack_slot); + } + else { + // if init method is not set, jump to referenced flow and step + ux_flow_init( + stack_slot, + STEPSPIC(STEPPIC(G_ux.flow_stack[stack_slot].steps[G_ux.flow_stack[stack_slot].index]) + ->validate_flow), + (const ux_flow_step_t *) PIC( + STEPPIC(G_ux.flow_stack[stack_slot].steps[G_ux.flow_stack[stack_slot].index]) + ->params)); + } } -void ux_flow_next_no_display(void) { - ux_flow_next_internal(0); +static void ux_flow_next_internal(unsigned int display_step) +{ + unsigned int top_stack_slot = G_ux.stack_count - 1; + + // last reached already (need validation, not next) + if (!ux_flow_check_valid() || G_ux.flow_stack[top_stack_slot].steps == NULL + || G_ux.flow_stack[top_stack_slot].length <= 1 + || G_ux.flow_stack[top_stack_slot].index >= G_ux.flow_stack[top_stack_slot].length - 1) { + return; + } + + // followed by a flow barrier ? => need validation instead of next + if (G_ux.flow_stack[top_stack_slot].index <= G_ux.flow_stack[top_stack_slot].length - 2) { + if (G_ux.flow_stack[top_stack_slot].steps[G_ux.flow_stack[top_stack_slot].index + 1] + == FLOW_BARRIER) { + return; + } + + // followed by a flow barrier ? => need validation instead of next + if (G_ux.flow_stack[top_stack_slot].steps[G_ux.flow_stack[top_stack_slot].index + 1] + == FLOW_LOOP) { + // display first step, fake direction as forward + G_ux.flow_stack[top_stack_slot].prev_index = G_ux.flow_stack[top_stack_slot].index = 0; + ux_flow_engine_init_step(top_stack_slot); + return; + } + } + + // advance flow pointer and display it (skip META STEPS) + G_ux.flow_stack[top_stack_slot].prev_index = G_ux.flow_stack[top_stack_slot].index; + G_ux.flow_stack[top_stack_slot].index++; + if (display_step) { + ux_flow_engine_init_step(top_stack_slot); + } } -void ux_flow_next(void) { - ux_flow_next_internal(1); +void ux_flow_next_no_display(void) +{ + ux_flow_next_internal(0); } -void ux_flow_prev(void) { - unsigned int top_stack_slot = G_ux.stack_count - 1; - - // first reached already - if (!ux_flow_check_valid() - || G_ux.flow_stack[top_stack_slot].steps == NULL - || G_ux.flow_stack[top_stack_slot].length <= 1 - || (G_ux.flow_stack[top_stack_slot].index == 0 - && G_ux.flow_stack[top_stack_slot].steps[G_ux.flow_stack[top_stack_slot].length-1] != FLOW_LOOP)) { - return; - } - - // loop in flow (before checking barrier as there is no prestep when looping) - if (G_ux.flow_stack[top_stack_slot].index == 0 - && G_ux.flow_stack[top_stack_slot].steps[G_ux.flow_stack[top_stack_slot].length-1] == FLOW_LOOP) { - // display last step (shall skip BARRIER if any, but a flow finishing with a BARRIER is cryptic) - G_ux.flow_stack[top_stack_slot].index = G_ux.flow_stack[top_stack_slot].length-2; - // fact direction as backward - G_ux.flow_stack[top_stack_slot].prev_index = G_ux.flow_stack[top_stack_slot].index+1; - ux_flow_engine_init_step(top_stack_slot); - return; - } - - // previous item is a flow barrier ? - if (G_ux.flow_stack[top_stack_slot].steps[G_ux.flow_stack[top_stack_slot].index-1] == FLOW_BARRIER) { - return; - } - - // advance flow pointer and display it (skip META STEPS) - G_ux.flow_stack[top_stack_slot].prev_index = G_ux.flow_stack[top_stack_slot].index; - G_ux.flow_stack[top_stack_slot].index--; - - ux_flow_engine_init_step(top_stack_slot); +void ux_flow_next(void) +{ + ux_flow_next_internal(1); } -void ux_flow_validate(void) { - unsigned int top_stack_slot = G_ux.stack_count - 1; - - // no flow ? - if (!ux_flow_check_valid() - || G_ux.flow_stack[top_stack_slot].steps == NULL - || G_ux.flow_stack[top_stack_slot].length == 0 - || G_ux.flow_stack[top_stack_slot].index >= G_ux.flow_stack[top_stack_slot].length) { - return; - } - - // no validation flow ? - if (STEPPIC(G_ux.flow_stack[top_stack_slot].steps[G_ux.flow_stack[top_stack_slot].index])->validate_flow != NULL) { - // execute validation flow - ux_flow_init(top_stack_slot, STEPSPIC(STEPPIC(G_ux.flow_stack[top_stack_slot].steps[G_ux.flow_stack[top_stack_slot].index])->validate_flow), NULL); - } - else { - // if next is a barrier, then proceed to the item after the barrier - // if NOT followed by a barrier, then validation is only performed through - // a validate_flow specified in the step, else ignored - if (G_ux.flow_stack[top_stack_slot].length > 0 - && G_ux.flow_stack[top_stack_slot].index <= G_ux.flow_stack[top_stack_slot].length - 2) { - - if (G_ux.flow_stack[top_stack_slot].steps[G_ux.flow_stack[top_stack_slot].index+1] == FLOW_BARRIER) { - - // take into account multi barrier at once, kthx poor code review - while (G_ux.flow_stack[top_stack_slot].length > 0 - && G_ux.flow_stack[top_stack_slot].index <= G_ux.flow_stack[top_stack_slot].length - 2 - && G_ux.flow_stack[top_stack_slot].steps[G_ux.flow_stack[top_stack_slot].index+1] == FLOW_BARRIER) { - G_ux.flow_stack[top_stack_slot].index++; - } - // skip to next step - G_ux.flow_stack[top_stack_slot].prev_index = G_ux.flow_stack[top_stack_slot].index; - G_ux.flow_stack[top_stack_slot].index++; - - // execute reached step - ux_flow_engine_init_step(top_stack_slot); - } - // reached the last step, but step if FLOW_LOOP - else if (G_ux.flow_stack[top_stack_slot].steps[G_ux.flow_stack[top_stack_slot].index+1] == FLOW_LOOP) { - // we go the forward direction - G_ux.flow_stack[top_stack_slot].prev_index = G_ux.flow_stack[top_stack_slot].index = 0; - // execute reached step - ux_flow_engine_init_step(top_stack_slot); - } - } - } +void ux_flow_prev(void) +{ + unsigned int top_stack_slot = G_ux.stack_count - 1; + + // first reached already + if (!ux_flow_check_valid() || G_ux.flow_stack[top_stack_slot].steps == NULL + || G_ux.flow_stack[top_stack_slot].length <= 1 + || (G_ux.flow_stack[top_stack_slot].index == 0 + && G_ux.flow_stack[top_stack_slot].steps[G_ux.flow_stack[top_stack_slot].length - 1] + != FLOW_LOOP)) { + return; + } + + // loop in flow (before checking barrier as there is no prestep when looping) + if (G_ux.flow_stack[top_stack_slot].index == 0 + && G_ux.flow_stack[top_stack_slot].steps[G_ux.flow_stack[top_stack_slot].length - 1] + == FLOW_LOOP) { + // display last step (shall skip BARRIER if any, but a flow finishing with a BARRIER is + // cryptic) + G_ux.flow_stack[top_stack_slot].index = G_ux.flow_stack[top_stack_slot].length - 2; + // fact direction as backward + G_ux.flow_stack[top_stack_slot].prev_index = G_ux.flow_stack[top_stack_slot].index + 1; + ux_flow_engine_init_step(top_stack_slot); + return; + } + + // previous item is a flow barrier ? + if (G_ux.flow_stack[top_stack_slot].steps[G_ux.flow_stack[top_stack_slot].index - 1] + == FLOW_BARRIER) { + return; + } + + // advance flow pointer and display it (skip META STEPS) + G_ux.flow_stack[top_stack_slot].prev_index = G_ux.flow_stack[top_stack_slot].index; + G_ux.flow_stack[top_stack_slot].index--; + + ux_flow_engine_init_step(top_stack_slot); } -void ux_flow_error(unsigned int error) { - UNUSED(error); - - unsigned int top_stack_slot = G_ux.stack_count - 1; - - if (G_ux.flow_stack[top_stack_slot].steps == NULL - || G_ux.flow_stack[top_stack_slot].length == 0 - || G_ux.flow_stack[top_stack_slot].index >= G_ux.flow_stack[top_stack_slot].length) { - return; - } +void ux_flow_validate(void) +{ + unsigned int top_stack_slot = G_ux.stack_count - 1; + + // no flow ? + if (!ux_flow_check_valid() || G_ux.flow_stack[top_stack_slot].steps == NULL + || G_ux.flow_stack[top_stack_slot].length == 0 + || G_ux.flow_stack[top_stack_slot].index >= G_ux.flow_stack[top_stack_slot].length) { + return; + } + + // no validation flow ? + if (STEPPIC(G_ux.flow_stack[top_stack_slot].steps[G_ux.flow_stack[top_stack_slot].index]) + ->validate_flow + != NULL) { + // execute validation flow + ux_flow_init(top_stack_slot, + STEPSPIC(STEPPIC(G_ux.flow_stack[top_stack_slot] + .steps[G_ux.flow_stack[top_stack_slot].index]) + ->validate_flow), + NULL); + } + else { + // if next is a barrier, then proceed to the item after the barrier + // if NOT followed by a barrier, then validation is only performed through + // a validate_flow specified in the step, else ignored + if (G_ux.flow_stack[top_stack_slot].length > 0 + && G_ux.flow_stack[top_stack_slot].index + <= G_ux.flow_stack[top_stack_slot].length - 2) { + if (G_ux.flow_stack[top_stack_slot].steps[G_ux.flow_stack[top_stack_slot].index + 1] + == FLOW_BARRIER) { + // take into account multi barrier at once, kthx poor code review + while (G_ux.flow_stack[top_stack_slot].length > 0 + && G_ux.flow_stack[top_stack_slot].index + <= G_ux.flow_stack[top_stack_slot].length - 2 + && G_ux.flow_stack[top_stack_slot] + .steps[G_ux.flow_stack[top_stack_slot].index + 1] + == FLOW_BARRIER) { + G_ux.flow_stack[top_stack_slot].index++; + } + // skip to next step + G_ux.flow_stack[top_stack_slot].prev_index = G_ux.flow_stack[top_stack_slot].index; + G_ux.flow_stack[top_stack_slot].index++; + + // execute reached step + ux_flow_engine_init_step(top_stack_slot); + } + // reached the last step, but step if FLOW_LOOP + else if (G_ux.flow_stack[top_stack_slot] + .steps[G_ux.flow_stack[top_stack_slot].index + 1] + == FLOW_LOOP) { + // we go the forward direction + G_ux.flow_stack[top_stack_slot].prev_index = G_ux.flow_stack[top_stack_slot].index + = 0; + // execute reached step + ux_flow_engine_init_step(top_stack_slot); + } + } + } +} - if (STEPPIC(G_ux.flow_stack[top_stack_slot].steps[G_ux.flow_stack[top_stack_slot].index])->error_flow != NULL) { - ux_flow_init(top_stack_slot, STEPSPIC(STEPPIC(G_ux.flow_stack[top_stack_slot].steps[G_ux.flow_stack[top_stack_slot].index])->error_flow), NULL); - } +void ux_flow_error(unsigned int error) +{ + UNUSED(error); + + unsigned int top_stack_slot = G_ux.stack_count - 1; + + if (G_ux.flow_stack[top_stack_slot].steps == NULL || G_ux.flow_stack[top_stack_slot].length == 0 + || G_ux.flow_stack[top_stack_slot].index >= G_ux.flow_stack[top_stack_slot].length) { + return; + } + + if (STEPPIC(G_ux.flow_stack[top_stack_slot].steps[G_ux.flow_stack[top_stack_slot].index]) + ->error_flow + != NULL) { + ux_flow_init(top_stack_slot, + STEPSPIC(STEPPIC(G_ux.flow_stack[top_stack_slot] + .steps[G_ux.flow_stack[top_stack_slot].index]) + ->error_flow), + NULL); + } } /** * Last step is marked with a FLOW_END_STEP value */ -void ux_flow_init(unsigned int stack_slot, const ux_flow_step_t* const * steps, const ux_flow_step_t* const start_step) { - if (stack_slot >= UX_STACK_SLOT_COUNT) { - return; - } - - G_ux.flow_stack[stack_slot].length = G_ux.flow_stack[stack_slot].prev_index = G_ux.flow_stack[stack_slot].index = 0; - G_ux.flow_stack[stack_slot].steps = NULL; - - // reset paging to avoid troubles if first step is a paginated step - memset(&G_ux.layout_paging, 0, sizeof(G_ux.layout_paging)); - - if (steps) { - G_ux.flow_stack[stack_slot].steps = STEPSPIC(steps); - while(G_ux.flow_stack[stack_slot].steps[G_ux.flow_stack[stack_slot].length] != FLOW_END_STEP) { - G_ux.flow_stack[stack_slot].length++; - } - if (start_step != NULL) { - const ux_flow_step_t* const start_step2 = STEPPIC(start_step); - while(G_ux.flow_stack[stack_slot].steps[G_ux.flow_stack[stack_slot].index] != FLOW_END_STEP - && STEPPIC(G_ux.flow_stack[stack_slot].steps[G_ux.flow_stack[stack_slot].index]) != start_step2) { - G_ux.flow_stack[stack_slot].prev_index = G_ux.flow_stack[stack_slot].index; - G_ux.flow_stack[stack_slot].index++; - } - } - - // init step - ux_flow_engine_init_step(stack_slot); - } +void ux_flow_init(unsigned int stack_slot, + const ux_flow_step_t *const *steps, + const ux_flow_step_t *const start_step) +{ + if (stack_slot >= UX_STACK_SLOT_COUNT) { + return; + } + + G_ux.flow_stack[stack_slot].length = G_ux.flow_stack[stack_slot].prev_index + = G_ux.flow_stack[stack_slot].index = 0; + G_ux.flow_stack[stack_slot].steps = NULL; + + // reset paging to avoid troubles if first step is a paginated step + memset(&G_ux.layout_paging, 0, sizeof(G_ux.layout_paging)); + + if (steps) { + G_ux.flow_stack[stack_slot].steps = STEPSPIC(steps); + while (G_ux.flow_stack[stack_slot].steps[G_ux.flow_stack[stack_slot].length] + != FLOW_END_STEP) { + G_ux.flow_stack[stack_slot].length++; + } + if (start_step != NULL) { + const ux_flow_step_t *const start_step2 = STEPPIC(start_step); + while (G_ux.flow_stack[stack_slot].steps[G_ux.flow_stack[stack_slot].index] + != FLOW_END_STEP + && STEPPIC(G_ux.flow_stack[stack_slot].steps[G_ux.flow_stack[stack_slot].index]) + != start_step2) { + G_ux.flow_stack[stack_slot].prev_index = G_ux.flow_stack[stack_slot].index; + G_ux.flow_stack[stack_slot].index++; + } + } + + // init step + ux_flow_engine_init_step(stack_slot); + } } -void ux_flow_uninit(unsigned int stack_slot) { - if (stack_slot < UX_STACK_SLOT_COUNT) { - memset(&G_ux.flow_stack[stack_slot], 0, sizeof(G_ux.flow_stack[stack_slot])); - } +void ux_flow_uninit(unsigned int stack_slot) +{ + if (stack_slot < UX_STACK_SLOT_COUNT) { + memset(&G_ux.flow_stack[stack_slot], 0, sizeof(G_ux.flow_stack[stack_slot])); + } } -unsigned int ux_flow_button_callback(unsigned int button_mask, unsigned int button_mask_counter) { - UNUSED(button_mask_counter); - switch(button_mask) { - case BUTTON_EVT_RELEASED|BUTTON_LEFT: - ux_flow_prev(); - break; - case BUTTON_EVT_RELEASED|BUTTON_RIGHT: - ux_flow_next(); - break; - case BUTTON_EVT_RELEASED|BUTTON_LEFT|BUTTON_RIGHT: - ux_flow_validate(); - break; - } - return 0; +unsigned int ux_flow_button_callback(unsigned int button_mask, unsigned int button_mask_counter) +{ + UNUSED(button_mask_counter); + switch (button_mask) { + case BUTTON_EVT_RELEASED | BUTTON_LEFT: + ux_flow_prev(); + break; + case BUTTON_EVT_RELEASED | BUTTON_RIGHT: + ux_flow_next(); + break; + case BUTTON_EVT_RELEASED | BUTTON_LEFT | BUTTON_RIGHT: + ux_flow_validate(); + break; + } + return 0; } -const void* ux_stack_get_step_params(unsigned int stack_slot) { - if (stack_slot >= UX_STACK_SLOT_COUNT) { - return NULL; - } +const void *ux_stack_get_step_params(unsigned int stack_slot) +{ + if (stack_slot >= UX_STACK_SLOT_COUNT) { + return NULL; + } - if (G_ux.flow_stack[stack_slot].length == 0) { - return NULL; - } + if (G_ux.flow_stack[stack_slot].length == 0) { + return NULL; + } - if (G_ux.flow_stack[stack_slot].index >= G_ux.flow_stack[stack_slot].length) { - return NULL; - } + if (G_ux.flow_stack[stack_slot].index >= G_ux.flow_stack[stack_slot].length) { + return NULL; + } - return PIC(STEPPIC(STEPSPIC(G_ux.flow_stack[stack_slot].steps)[G_ux.flow_stack[stack_slot].index])->params); + return PIC( + STEPPIC(STEPSPIC(G_ux.flow_stack[stack_slot].steps)[G_ux.flow_stack[stack_slot].index]) + ->params); } -const void* ux_stack_get_current_step_params(void) { - unsigned int top_stack_slot = G_ux.stack_count - 1; +const void *ux_stack_get_current_step_params(void) +{ + unsigned int top_stack_slot = G_ux.stack_count - 1; - return ux_stack_get_step_params(top_stack_slot); + return ux_stack_get_step_params(top_stack_slot); } -unsigned int ux_flow_relayout(void) { - // if a flow is defined and valid - if (ux_flow_get_current() != NULL) { - unsigned int top_stack_slot = G_ux.stack_count - 1; +unsigned int ux_flow_relayout(void) +{ + // if a flow is defined and valid + if (ux_flow_get_current() != NULL) { + unsigned int top_stack_slot = G_ux.stack_count - 1; - ux_flow_engine_init_step(top_stack_slot); - return 1; - } - return 0; + ux_flow_engine_init_step(top_stack_slot); + return 1; + } + return 0; } -#endif // HAVE_UX_FLOW +#endif // HAVE_UX_FLOW diff --git a/lib_ux/src/ux_layout_bb.c b/lib_ux/src/ux_layout_bb.c index d119bed02..ef47b22a1 100644 --- a/lib_ux/src/ux_layout_bb.c +++ b/lib_ux/src/ux_layout_bb.c @@ -1,20 +1,20 @@ /******************************************************************************* -* Ledger Nano S - Secure firmware -* (c) 2022 Ledger -* -* Licensed under the Apache License, Version 2.0 (the "License"); -* you may not use this file except in compliance with the License. -* You may obtain a copy of the License at -* -* http://www.apache.org/licenses/LICENSE-2.0 -* -* Unless required by applicable law or agreed to in writing, software -* distributed under the License is distributed on an "AS IS" BASIS, -* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -* See the License for the specific language governing permissions and -* limitations under the License. -********************************************************************************/ + * Ledger Nano S - Secure firmware + * (c) 2022 Ledger + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT 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 "ux.h" #include "os_utils.h" @@ -26,6 +26,7 @@ * 2 bold text lines */ +// clang-format off const bagl_element_t ux_layout_bb_elements[] = { #if (BAGL_WIDTH==128 && BAGL_HEIGHT==64) // erase @@ -51,19 +52,22 @@ const bagl_element_t ux_layout_bb_elements[] = { #error "BAGL_WIDTH/BAGL_HEIGHT not defined" #endif }; +// clang-format on -void ux_layout_bb_init_common(unsigned int stack_slot) { - ux_stack_init(stack_slot); - G_ux.stack[stack_slot].element_arrays[0].element_array = ux_layout_bb_elements; - G_ux.stack[stack_slot].element_arrays[0].element_array_count = ARRAYLEN(ux_layout_bb_elements); - G_ux.stack[stack_slot].element_arrays_count = 1; - G_ux.stack[stack_slot].button_push_callback = ux_flow_button_callback; +void ux_layout_bb_init_common(unsigned int stack_slot) +{ + ux_stack_init(stack_slot); + G_ux.stack[stack_slot].element_arrays[0].element_array = ux_layout_bb_elements; + G_ux.stack[stack_slot].element_arrays[0].element_array_count = ARRAYLEN(ux_layout_bb_elements); + G_ux.stack[stack_slot].element_arrays_count = 1; + G_ux.stack[stack_slot].button_push_callback = ux_flow_button_callback; } -void ux_layout_bb_init(unsigned int stack_slot) { - ux_layout_bb_init_common(stack_slot); - G_ux.stack[stack_slot].screen_before_element_display_callback = ux_layout_strings_prepro; - ux_stack_display(stack_slot); +void ux_layout_bb_init(unsigned int stack_slot) +{ + ux_layout_bb_init_common(stack_slot); + G_ux.stack[stack_slot].screen_before_element_display_callback = ux_layout_strings_prepro; + ux_stack_display(stack_slot); } -#endif // HAVE_UX_FLOW +#endif // HAVE_UX_FLOW diff --git a/lib_ux/src/ux_layout_bn.c b/lib_ux/src/ux_layout_bn.c index 43ef18bb2..68a48de5d 100644 --- a/lib_ux/src/ux_layout_bn.c +++ b/lib_ux/src/ux_layout_bn.c @@ -1,20 +1,20 @@ /******************************************************************************* -* Ledger Nano S - Secure firmware -* (c) 2022 Ledger -* -* Licensed under the Apache License, Version 2.0 (the "License"); -* you may not use this file except in compliance with the License. -* You may obtain a copy of the License at -* -* http://www.apache.org/licenses/LICENSE-2.0 -* -* Unless required by applicable law or agreed to in writing, software -* distributed under the License is distributed on an "AS IS" BASIS, -* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -* See the License for the specific language governing permissions and -* limitations under the License. -********************************************************************************/ + * Ledger Nano S - Secure firmware + * (c) 2022 Ledger + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT 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 "ux.h" #include "ux_layout_common.h" @@ -27,18 +27,21 @@ * Uses layout from ux_layout_bb */ -const bagl_element_t* ux_layout_bn_prepro(const bagl_element_t* element) { - const bagl_element_t* e = ux_layout_strings_prepro(element); - if (e && G_ux.tmp_element.component.userid == 0x11) { - G_ux.tmp_element.component.font_id = BAGL_FONT_OPEN_SANS_REGULAR_11px|BAGL_FONT_ALIGNMENT_CENTER; - } - return e; +const bagl_element_t *ux_layout_bn_prepro(const bagl_element_t *element) +{ + const bagl_element_t *e = ux_layout_strings_prepro(element); + if (e && G_ux.tmp_element.component.userid == 0x11) { + G_ux.tmp_element.component.font_id + = BAGL_FONT_OPEN_SANS_REGULAR_11px | BAGL_FONT_ALIGNMENT_CENTER; + } + return e; } -void ux_layout_bn_init(unsigned int stack_slot) { - ux_layout_bb_init_common(stack_slot); - G_ux.stack[stack_slot].screen_before_element_display_callback = ux_layout_bn_prepro; - ux_stack_display(stack_slot); +void ux_layout_bn_init(unsigned int stack_slot) +{ + ux_layout_bb_init_common(stack_slot); + G_ux.stack[stack_slot].screen_before_element_display_callback = ux_layout_bn_prepro; + ux_stack_display(stack_slot); } -#endif // HAVE_UX_FLOW +#endif // HAVE_UX_FLOW diff --git a/lib_ux/src/ux_layout_bnn.c b/lib_ux/src/ux_layout_bnn.c index 8fe753013..7a54d9111 100644 --- a/lib_ux/src/ux_layout_bnn.c +++ b/lib_ux/src/ux_layout_bnn.c @@ -1,31 +1,32 @@ /******************************************************************************* -* Ledger Nano S - Secure firmware -* (c) 2022 Ledger -* -* Licensed under the Apache License, Version 2.0 (the "License"); -* you may not use this file except in compliance with the License. -* You may obtain a copy of the License at -* -* http://www.apache.org/licenses/LICENSE-2.0 -* -* Unless required by applicable law or agreed to in writing, software -* distributed under the License is distributed on an "AS IS" BASIS, -* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -* See the License for the specific language governing permissions and -* limitations under the License. -********************************************************************************/ + * Ledger Nano S - Secure firmware + * (c) 2022 Ledger + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT 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 "ux.h" #include "os_utils.h" #ifdef HAVE_UX_FLOW -#if (BAGL_WIDTH==128 && BAGL_HEIGHT==64) +#if (BAGL_WIDTH == 128 && BAGL_HEIGHT == 64) /********************************************************************************* * 4 text lines */ +// clang-format off const bagl_element_t ux_layout_bnn_elements[] = { // erase {{BAGL_RECTANGLE , 0x00, 0, 0, 128, 64, 0, 0, BAGL_FILL, 0x000000, 0xFFFFFF, 0, 0}, .text=NULL}, @@ -37,16 +38,18 @@ const bagl_element_t ux_layout_bnn_elements[] = { {{BAGL_LABELINE , 0x11, 6, 36, 116, 32, 0, 0, 0 , 0xFFFFFF, 0x000000, BAGL_FONT_OPEN_SANS_REGULAR_11px|BAGL_FONT_ALIGNMENT_CENTER, 0 }, .text=NULL}, {{BAGL_LABELINE , 0x12, 6, 52, 116, 32, 0, 0, 0 , 0xFFFFFF, 0x000000, BAGL_FONT_OPEN_SANS_REGULAR_11px|BAGL_FONT_ALIGNMENT_CENTER, 0 }, .text=NULL}, }; - -void ux_layout_bnn_init(unsigned int stack_slot) { - ux_stack_init(stack_slot); - G_ux.stack[stack_slot].element_arrays[0].element_array = ux_layout_bnn_elements; - G_ux.stack[stack_slot].element_arrays[0].element_array_count = ARRAYLEN(ux_layout_bnn_elements); - G_ux.stack[stack_slot].element_arrays_count = 1; - G_ux.stack[stack_slot].screen_before_element_display_callback = ux_layout_strings_prepro; - G_ux.stack[stack_slot].button_push_callback = ux_flow_button_callback; - ux_stack_display(stack_slot); +// clang-format on + +void ux_layout_bnn_init(unsigned int stack_slot) +{ + ux_stack_init(stack_slot); + G_ux.stack[stack_slot].element_arrays[0].element_array = ux_layout_bnn_elements; + G_ux.stack[stack_slot].element_arrays[0].element_array_count = ARRAYLEN(ux_layout_bnn_elements); + G_ux.stack[stack_slot].element_arrays_count = 1; + G_ux.stack[stack_slot].screen_before_element_display_callback = ux_layout_strings_prepro; + G_ux.stack[stack_slot].button_push_callback = ux_flow_button_callback; + ux_stack_display(stack_slot); } -#endif // (BAGL_WIDTH==128 && BAGL_HEIGHT==64) +#endif // (BAGL_WIDTH==128 && BAGL_HEIGHT==64) -#endif // HAVE_UX_FLOW +#endif // HAVE_UX_FLOW diff --git a/lib_ux/src/ux_layout_bnnn.c b/lib_ux/src/ux_layout_bnnn.c index be8a46584..0c71f2c0a 100644 --- a/lib_ux/src/ux_layout_bnnn.c +++ b/lib_ux/src/ux_layout_bnnn.c @@ -1,32 +1,33 @@ /******************************************************************************* -* Ledger Nano S - Secure firmware -* (c) 2022 Ledger -* -* Licensed under the Apache License, Version 2.0 (the "License"); -* you may not use this file except in compliance with the License. -* You may obtain a copy of the License at -* -* http://www.apache.org/licenses/LICENSE-2.0 -* -* Unless required by applicable law or agreed to in writing, software -* distributed under the License is distributed on an "AS IS" BASIS, -* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -* See the License for the specific language governing permissions and -* limitations under the License. -********************************************************************************/ + * Ledger Nano S - Secure firmware + * (c) 2022 Ledger + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT 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 "ux.h" #include "os_utils.h" #ifdef HAVE_UX_FLOW -#if (BAGL_WIDTH==128 && BAGL_HEIGHT==64) +#if (BAGL_WIDTH == 128 && BAGL_HEIGHT == 64) /********************************************************************************* * 1 bold text line * 3 text lines */ +// clang-format off const bagl_element_t ux_layout_bnnn_elements[] = { // erase {{BAGL_RECTANGLE , 0x00, 0, 0, 128, 64, 0, 0, BAGL_FILL, 0x000000, 0xFFFFFF, 0, 0}, .text=NULL}, @@ -39,16 +40,19 @@ const bagl_element_t ux_layout_bnnn_elements[] = { {{BAGL_LABELINE , 0x12, 6, 43, 116, 32, 0, 0, 0 , 0xFFFFFF, 0x000000, BAGL_FONT_OPEN_SANS_REGULAR_11px|BAGL_FONT_ALIGNMENT_CENTER, 0 }, .text=NULL}, {{BAGL_LABELINE , 0x13, 6, 57, 116, 32, 0, 0, 0 , 0xFFFFFF, 0x000000, BAGL_FONT_OPEN_SANS_REGULAR_11px|BAGL_FONT_ALIGNMENT_CENTER, 0 }, .text=NULL}, }; - -void ux_layout_bnnn_init(unsigned int stack_slot) { - ux_stack_init(stack_slot); - G_ux.stack[stack_slot].element_arrays[0].element_array = ux_layout_bnnn_elements; - G_ux.stack[stack_slot].element_arrays[0].element_array_count = ARRAYLEN(ux_layout_bnnn_elements); - G_ux.stack[stack_slot].element_arrays_count = 1; - G_ux.stack[stack_slot].screen_before_element_display_callback = ux_layout_strings_prepro; - G_ux.stack[stack_slot].button_push_callback = ux_flow_button_callback; - ux_stack_display(stack_slot); +// clang-format on + +void ux_layout_bnnn_init(unsigned int stack_slot) +{ + ux_stack_init(stack_slot); + G_ux.stack[stack_slot].element_arrays[0].element_array = ux_layout_bnnn_elements; + G_ux.stack[stack_slot].element_arrays[0].element_array_count + = ARRAYLEN(ux_layout_bnnn_elements); + G_ux.stack[stack_slot].element_arrays_count = 1; + G_ux.stack[stack_slot].screen_before_element_display_callback = ux_layout_strings_prepro; + G_ux.stack[stack_slot].button_push_callback = ux_flow_button_callback; + ux_stack_display(stack_slot); } -#endif // (BAGL_WIDTH==128 && BAGL_HEIGHT==64) +#endif // (BAGL_WIDTH==128 && BAGL_HEIGHT==64) -#endif // HAVE_UX_FLOW +#endif // HAVE_UX_FLOW diff --git a/lib_ux/src/ux_layout_common.h b/lib_ux/src/ux_layout_common.h index 0ddc320e6..9f3a1bf78 100644 --- a/lib_ux/src/ux_layout_common.h +++ b/lib_ux/src/ux_layout_common.h @@ -10,15 +10,17 @@ typedef void (*ux_layout_paging_redisplay_t)(unsigned int stack_slot); void ux_layout_bb_init_common(unsigned int stack_slot); -const bagl_element_t* ux_layout_pbb_prepro(const bagl_element_t* element); -void ux_layout_pbb_init_common(unsigned int stack_slot); +const bagl_element_t *ux_layout_pbb_prepro(const bagl_element_t *element); +void ux_layout_pbb_init_common(unsigned int stack_slot); #if defined(HAVE_INDEXED_STRINGS) -void ux_layout_pages_init_common(unsigned int stack_slot, const char* text, ux_layout_paging_redisplay_t redisplay); -#endif //defined(HAVE_INDEXED_STRINGS) +void ux_layout_pages_init_common(unsigned int stack_slot, + const char *text, + ux_layout_paging_redisplay_t redisplay); +#endif // defined(HAVE_INDEXED_STRINGS) +void ux_layout_pages_display_init(const char *text); +const bagl_element_t *ux_layout_pages_display_element(const bagl_element_t *element, + const char *text); -void ux_layout_pages_display_init(const char* text); -const bagl_element_t* ux_layout_pages_display_element(const bagl_element_t* element, const char* text); - -#endif // HAVE_UX_FLOW +#endif // HAVE_UX_FLOW diff --git a/lib_ux/src/ux_layout_nn.c b/lib_ux/src/ux_layout_nn.c index 1590e2a6a..49533b56c 100644 --- a/lib_ux/src/ux_layout_nn.c +++ b/lib_ux/src/ux_layout_nn.c @@ -1,20 +1,20 @@ /******************************************************************************* -* Ledger Nano S - Secure firmware -* (c) 2022 Ledger -* -* Licensed under the Apache License, Version 2.0 (the "License"); -* you may not use this file except in compliance with the License. -* You may obtain a copy of the License at -* -* http://www.apache.org/licenses/LICENSE-2.0 -* -* Unless required by applicable law or agreed to in writing, software -* distributed under the License is distributed on an "AS IS" BASIS, -* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -* See the License for the specific language governing permissions and -* limitations under the License. -********************************************************************************/ + * Ledger Nano S - Secure firmware + * (c) 2022 Ledger + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT 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 "ux.h" #include "ux_layout_common.h" @@ -26,18 +26,21 @@ * Uses bb layout */ -const bagl_element_t* ux_layout_nn_prepro(const bagl_element_t* element) { - const bagl_element_t* e = ux_layout_strings_prepro(element); - if (e && G_ux.tmp_element.component.userid >= 0x10) { - G_ux.tmp_element.component.font_id = BAGL_FONT_OPEN_SANS_REGULAR_11px|BAGL_FONT_ALIGNMENT_CENTER; - } - return e; +const bagl_element_t *ux_layout_nn_prepro(const bagl_element_t *element) +{ + const bagl_element_t *e = ux_layout_strings_prepro(element); + if (e && G_ux.tmp_element.component.userid >= 0x10) { + G_ux.tmp_element.component.font_id + = BAGL_FONT_OPEN_SANS_REGULAR_11px | BAGL_FONT_ALIGNMENT_CENTER; + } + return e; } -void ux_layout_nn_init(unsigned int stack_slot) { - ux_layout_bb_init_common(stack_slot); - G_ux.stack[stack_slot].screen_before_element_display_callback = ux_layout_nn_prepro; - ux_stack_display(stack_slot); +void ux_layout_nn_init(unsigned int stack_slot) +{ + ux_layout_bb_init_common(stack_slot); + G_ux.stack[stack_slot].screen_before_element_display_callback = ux_layout_nn_prepro; + ux_stack_display(stack_slot); } -#endif // HAVE_UX_FLOW +#endif // HAVE_UX_FLOW diff --git a/lib_ux/src/ux_layout_nnbnn.c b/lib_ux/src/ux_layout_nnbnn.c index 74a294234..2dfd5a071 100644 --- a/lib_ux/src/ux_layout_nnbnn.c +++ b/lib_ux/src/ux_layout_nnbnn.c @@ -1,20 +1,20 @@ /******************************************************************************* -* Ledger Nano S - Secure firmware -* (c) 2022 Ledger -* -* Licensed under the Apache License, Version 2.0 (the "License"); -* you may not use this file except in compliance with the License. -* You may obtain a copy of the License at -* -* http://www.apache.org/licenses/LICENSE-2.0 -* -* Unless required by applicable law or agreed to in writing, software -* distributed under the License is distributed on an "AS IS" BASIS, -* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -* See the License for the specific language governing permissions and -* limitations under the License. -********************************************************************************/ + * Ledger Nano S - Secure firmware + * (c) 2022 Ledger + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT 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 "ux.h" #include "os_utils.h" @@ -29,6 +29,7 @@ * 1/2 text lines */ +// clang-format off const bagl_element_t ux_layout_nnbnn_elements[] = { #if (BAGL_WIDTH==128 && BAGL_HEIGHT==64) // erase @@ -58,53 +59,54 @@ const bagl_element_t ux_layout_nnbnn_elements[] = { #error "BAGL_WIDTH/BAGL_HEIGHT not defined" #endif }; - -const bagl_element_t* ux_layout_nnbnn_prepro(const bagl_element_t* element) { - // don't display if null - const void *params = ux_stack_get_current_step_params(); - - // copy element before any mod - memmove(&G_ux.tmp_element, element, sizeof(bagl_element_t)); - - // for dashboard, setup the current application's name - switch (element->component.userid) { - - case 0x01: - { - if (!((const ux_layout_strings_params_t*)params)->lines[1]) { - return NULL; - } - break; - } - - case 0x02: - { - if (!((const ux_layout_strings_params_t*)params)->lines[3]) { - return NULL; - } - break; - } - case 0x10: - case 0x11: - case 0x12: - case 0x13: - case 0x14: - { - G_ux.tmp_element.text = ((const ux_layout_strings_params_t*)params)->lines[G_ux.tmp_element.component.userid&0xF]; - break; +// clang-format on + +const bagl_element_t *ux_layout_nnbnn_prepro(const bagl_element_t *element) +{ + // don't display if null + const void *params = ux_stack_get_current_step_params(); + + // copy element before any mod + memmove(&G_ux.tmp_element, element, sizeof(bagl_element_t)); + + // for dashboard, setup the current application's name + switch (element->component.userid) { + case 0x01: { + if (!((const ux_layout_strings_params_t *) params)->lines[1]) { + return NULL; + } + break; + } + + case 0x02: { + if (!((const ux_layout_strings_params_t *) params)->lines[3]) { + return NULL; + } + break; + } + case 0x10: + case 0x11: + case 0x12: + case 0x13: + case 0x14: { + G_ux.tmp_element.text = ((const ux_layout_strings_params_t *) params) + ->lines[G_ux.tmp_element.component.userid & 0xF]; + break; + } } - } - return &G_ux.tmp_element; + return &G_ux.tmp_element; } -void ux_layout_nnbnn_init(unsigned int stack_slot) { - ux_stack_init(stack_slot); - G_ux.stack[stack_slot].element_arrays[0].element_array = ux_layout_nnbnn_elements; - G_ux.stack[stack_slot].element_arrays[0].element_array_count = ARRAYLEN(ux_layout_nnbnn_elements); - G_ux.stack[stack_slot].element_arrays_count = 1; - G_ux.stack[stack_slot].screen_before_element_display_callback = ux_layout_nnbnn_prepro; - G_ux.stack[stack_slot].button_push_callback = ux_flow_button_callback; - ux_stack_display(stack_slot); +void ux_layout_nnbnn_init(unsigned int stack_slot) +{ + ux_stack_init(stack_slot); + G_ux.stack[stack_slot].element_arrays[0].element_array = ux_layout_nnbnn_elements; + G_ux.stack[stack_slot].element_arrays[0].element_array_count + = ARRAYLEN(ux_layout_nnbnn_elements); + G_ux.stack[stack_slot].element_arrays_count = 1; + G_ux.stack[stack_slot].screen_before_element_display_callback = ux_layout_nnbnn_prepro; + G_ux.stack[stack_slot].button_push_callback = ux_flow_button_callback; + ux_stack_display(stack_slot); } -#endif // HAVE_UX_FLOW +#endif // HAVE_UX_FLOW diff --git a/lib_ux/src/ux_layout_nnn.c b/lib_ux/src/ux_layout_nnn.c index f93f61b75..b5171c454 100644 --- a/lib_ux/src/ux_layout_nnn.c +++ b/lib_ux/src/ux_layout_nnn.c @@ -1,31 +1,32 @@ /******************************************************************************* -* Ledger Nano S - Secure firmware -* (c) 2022 Ledger -* -* Licensed under the Apache License, Version 2.0 (the "License"); -* you may not use this file except in compliance with the License. -* You may obtain a copy of the License at -* -* http://www.apache.org/licenses/LICENSE-2.0 -* -* Unless required by applicable law or agreed to in writing, software -* distributed under the License is distributed on an "AS IS" BASIS, -* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -* See the License for the specific language governing permissions and -* limitations under the License. -********************************************************************************/ + * Ledger Nano S - Secure firmware + * (c) 2022 Ledger + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT 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 "ux.h" #include "os_utils.h" #ifdef HAVE_UX_FLOW -#if (BAGL_WIDTH==128 && BAGL_HEIGHT==64) +#if (BAGL_WIDTH == 128 && BAGL_HEIGHT == 64) /********************************************************************************* * 3 text lines */ +// clang-format off const bagl_element_t ux_layout_nnn_elements[] = { // erase {{BAGL_RECTANGLE , 0x00, 0, 0, 128, 64, 0, 0, BAGL_FILL, 0x000000, 0xFFFFFF, 0, 0}, .text=NULL}, @@ -37,17 +38,19 @@ const bagl_element_t ux_layout_nnn_elements[] = { {{BAGL_LABELINE , 0x11, 6, 36, 116, 32, 0, 0, 0 , 0xFFFFFF, 0x000000, BAGL_FONT_OPEN_SANS_REGULAR_11px|BAGL_FONT_ALIGNMENT_CENTER, 0 }, .text=NULL}, {{BAGL_LABELINE , 0x12, 6, 52, 116, 32, 0, 0, 0 , 0xFFFFFF, 0x000000, BAGL_FONT_OPEN_SANS_REGULAR_11px|BAGL_FONT_ALIGNMENT_CENTER, 0 }, .text=NULL}, }; - -void ux_layout_nnn_init(unsigned int stack_slot) { - ux_stack_init(stack_slot); - G_ux.stack[stack_slot].element_arrays[0].element_array = ux_layout_nnn_elements; - G_ux.stack[stack_slot].element_arrays[0].element_array_count = ARRAYLEN(ux_layout_nnn_elements); - G_ux.stack[stack_slot].element_arrays_count = 1; - G_ux.stack[stack_slot].screen_before_element_display_callback = ux_layout_strings_prepro; - G_ux.stack[stack_slot].button_push_callback = ux_flow_button_callback; - ux_stack_display(stack_slot); +// clang-format on + +void ux_layout_nnn_init(unsigned int stack_slot) +{ + ux_stack_init(stack_slot); + G_ux.stack[stack_slot].element_arrays[0].element_array = ux_layout_nnn_elements; + G_ux.stack[stack_slot].element_arrays[0].element_array_count = ARRAYLEN(ux_layout_nnn_elements); + G_ux.stack[stack_slot].element_arrays_count = 1; + G_ux.stack[stack_slot].screen_before_element_display_callback = ux_layout_strings_prepro; + G_ux.stack[stack_slot].button_push_callback = ux_flow_button_callback; + ux_stack_display(stack_slot); } -#endif // (BAGL_WIDTH==128 && BAGL_HEIGHT==64) +#endif // (BAGL_WIDTH==128 && BAGL_HEIGHT==64) -#endif // HAVE_UX_FLOW +#endif // HAVE_UX_FLOW diff --git a/lib_ux/src/ux_layout_nnnn.c b/lib_ux/src/ux_layout_nnnn.c index 83a1087a5..5fed6b76c 100644 --- a/lib_ux/src/ux_layout_nnnn.c +++ b/lib_ux/src/ux_layout_nnnn.c @@ -1,31 +1,32 @@ /******************************************************************************* -* Ledger Nano S - Secure firmware -* (c) 2022 Ledger -* -* Licensed under the Apache License, Version 2.0 (the "License"); -* you may not use this file except in compliance with the License. -* You may obtain a copy of the License at -* -* http://www.apache.org/licenses/LICENSE-2.0 -* -* Unless required by applicable law or agreed to in writing, software -* distributed under the License is distributed on an "AS IS" BASIS, -* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -* See the License for the specific language governing permissions and -* limitations under the License. -********************************************************************************/ + * Ledger Nano S - Secure firmware + * (c) 2022 Ledger + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT 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 "ux.h" #include "os_utils.h" #ifdef HAVE_UX_FLOW -#if (BAGL_WIDTH==128 && BAGL_HEIGHT==64) +#if (BAGL_WIDTH == 128 && BAGL_HEIGHT == 64) /********************************************************************************* * 4 text lines */ +// clang-format off const bagl_element_t ux_layout_nnnn_elements[] = { // erase {{BAGL_RECTANGLE , 0x00, 0, 0, 128, 64, 0, 0, BAGL_FILL, 0x000000, 0xFFFFFF, 0, 0}, .text=NULL}, @@ -38,17 +39,20 @@ const bagl_element_t ux_layout_nnnn_elements[] = { {{BAGL_LABELINE , 0x12, 6, 43, 116, 32, 0, 0, 0 , 0xFFFFFF, 0x000000, BAGL_FONT_OPEN_SANS_REGULAR_11px|BAGL_FONT_ALIGNMENT_CENTER, 0 }, .text=NULL}, {{BAGL_LABELINE , 0x13, 6, 57, 116, 32, 0, 0, 0 , 0xFFFFFF, 0x000000, BAGL_FONT_OPEN_SANS_REGULAR_11px|BAGL_FONT_ALIGNMENT_CENTER, 0 }, .text=NULL}, }; - -void ux_layout_nnnn_init(unsigned int stack_slot) { - ux_stack_init(stack_slot); - G_ux.stack[stack_slot].element_arrays[0].element_array = ux_layout_nnnn_elements; - G_ux.stack[stack_slot].element_arrays[0].element_array_count = ARRAYLEN(ux_layout_nnnn_elements); - G_ux.stack[stack_slot].element_arrays_count = 1; - G_ux.stack[stack_slot].screen_before_element_display_callback = ux_layout_strings_prepro; - G_ux.stack[stack_slot].button_push_callback = ux_flow_button_callback; - ux_stack_display(stack_slot); +// clang-format on + +void ux_layout_nnnn_init(unsigned int stack_slot) +{ + ux_stack_init(stack_slot); + G_ux.stack[stack_slot].element_arrays[0].element_array = ux_layout_nnnn_elements; + G_ux.stack[stack_slot].element_arrays[0].element_array_count + = ARRAYLEN(ux_layout_nnnn_elements); + G_ux.stack[stack_slot].element_arrays_count = 1; + G_ux.stack[stack_slot].screen_before_element_display_callback = ux_layout_strings_prepro; + G_ux.stack[stack_slot].button_push_callback = ux_flow_button_callback; + ux_stack_display(stack_slot); } -#endif // (BAGL_WIDTH==128 && BAGL_HEIGHT==64) +#endif // (BAGL_WIDTH==128 && BAGL_HEIGHT==64) -#endif // HAVE_UX_FLOW +#endif // HAVE_UX_FLOW diff --git a/lib_ux/src/ux_layout_pages.c b/lib_ux/src/ux_layout_pages.c index 73cdf4f9b..2e78a6814 100644 --- a/lib_ux/src/ux_layout_pages.c +++ b/lib_ux/src/ux_layout_pages.c @@ -1,20 +1,20 @@ /******************************************************************************* -* Ledger Nano S - Secure firmware -* (c) 2022 Ledger -* -* Licensed under the Apache License, Version 2.0 (the "License"); -* you may not use this file except in compliance with the License. -* You may obtain a copy of the License at -* -* http://www.apache.org/licenses/LICENSE-2.0 -* -* Unless required by applicable law or agreed to in writing, software -* distributed under the License is distributed on an "AS IS" BASIS, -* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -* See the License for the specific language governing permissions and -* limitations under the License. -********************************************************************************/ + * Ledger Nano S - Secure firmware + * (c) 2022 Ledger + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT 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 "os_helpers.h" #include "os_math.h" #include "os_pic.h" @@ -33,6 +33,7 @@ #if (defined HAVE_BOLOS || defined(BUILD_PNG)) +// clang-format off static const bagl_element_t ux_layout_pages_elements[] = { #if (BAGL_WIDTH==128 && BAGL_HEIGHT==64) // Default Layout for LNX/LNS+: @@ -87,6 +88,7 @@ static const bagl_element_t ux_layout_pages_elements[] = { {{BAGL_LABELINE , 0x11, 6, 26, 116, 32, 0, 0, 0 , 0xFFFFFF, 0x000000, BAGL_FONT_OPEN_SANS_REGULAR_11px|BAGL_FONT_ALIGNMENT_CENTER, 0 }, .text=NULL}, #endif // (BAGL_WIDTH==128 && BAGL_HEIGHT==64) }; +// clang-format on // X Coordinate & width of text when there is an icon centered on the side: #define BAGL_ICON_TEXT_XCOORD 38 @@ -96,755 +98,805 @@ static const bagl_element_t ux_layout_pages_elements[] = { // This function will parse text and build arrays of txt ptr & lengths for each // line, taking in account specific contents like string buffer, side icons etc. // It returns a ptr to the side icon if there is one on the page (on any line). -const bagl_icon_details_t *update_lines_length(const char *text, const char *lines[], - unsigned short lengths[]) { - const bagl_icon_details_t *icon_details = NULL; - - // Override text parameter by a string buffer addr, eventually: - // (this is necessary when a string buffer is displayed over several pages) - const char *string_buffer = get_string_buffer(G_ux.layout_paging.string_buffer_id); - - // Parse all lines on this page to see if there is something special to do: - for (int i=0; i < UX_LAYOUT_PAGES_LINE_COUNT; i++) { - const char *txt; - unsigned short length = G_ux.layout_paging.lengths[i]; - - // When using UX_LOC_PAGING macro, first line contain the title - if (!i && G_ux.layout_paging.paging_title) { - const char *title = get_ux_loc_string(G_ux.layout_paging.paging_title-1); - if (title) { - SPRINTF(G_ux.string_buffer, (G_ux.layout_paging.count>1)?"%s (%d/%d)":"%s", title, G_ux.layout_paging.current+1, G_ux.layout_paging.count); - } else { - SPRINTF(G_ux.string_buffer, "%d/%d", G_ux.layout_paging.current+1, G_ux.layout_paging.count); - } - // Store text pointer & length for this line: - lines[0] = G_ux.string_buffer; - lengths[0] = strlen(G_ux.string_buffer); - continue; - } +const bagl_icon_details_t *update_lines_length(const char *text, + const char *lines[], + unsigned short lengths[]) +{ + const bagl_icon_details_t *icon_details = NULL; + + // Override text parameter by a string buffer addr, eventually: + // (this is necessary when a string buffer is displayed over several pages) + const char *string_buffer = get_string_buffer(G_ux.layout_paging.string_buffer_id); + + // Parse all lines on this page to see if there is something special to do: + for (int i = 0; i < UX_LAYOUT_PAGES_LINE_COUNT; i++) { + const char *txt; + unsigned short length = G_ux.layout_paging.lengths[i]; + + // When using UX_LOC_PAGING macro, first line contain the title + if (!i && G_ux.layout_paging.paging_title) { + const char *title = get_ux_loc_string(G_ux.layout_paging.paging_title - 1); + if (title) { + SPRINTF(G_ux.string_buffer, + (G_ux.layout_paging.count > 1) ? "%s (%d/%d)" : "%s", + title, + G_ux.layout_paging.current + 1, + G_ux.layout_paging.count); + } + else { + SPRINTF(G_ux.string_buffer, + "%d/%d", + G_ux.layout_paging.current + 1, + G_ux.layout_paging.count); + } + // Store text pointer & length for this line: + lines[0] = G_ux.string_buffer; + lengths[0] = strlen(G_ux.string_buffer); + continue; + } - // Is there anything to display on this line? - if (length == 0) { - lines[i] = NULL; - lengths[i] = 0; - continue; - } - if (string_buffer) { - txt = string_buffer; - } else if (text) { - txt = STRPIC(text); - } else { - txt = G_ux.externalText; - } - // Take in account offset which is relative to txt ptr: - txt += G_ux.layout_paging.offsets[i]; - - // Check if this line starts with an escape sequence: - while (txt && txt[0] == '\e') { - // There is at least one more byte which is readable. - // (even if it is the end of the string, it contains '\0') - unsigned short extra_byte = (unsigned char)txt[1]; - // Is it an icon? - if (extra_byte >= FIRST_GLYPHS_ICON && - extra_byte <= LAST_GLYPHS_ICON) { - // Does this line contain a 'left side icon'? - // If there is only an icon, then it is displayed on a full line. - // If there are text after the icon, it is displayed on left side. - // (=> This is what userid 0x0F is about!!) - if (length > 2) { - // This is a side icon => update icon_details ptr: - icon_details = get_glyphs_icon(extra_byte); - // Skip the side icon related bytes => update txt ptr & length: - txt += 2; - length -= 2; - // Skip all spaces characters after the side icon related bytes: - while (*txt == ' ' && length) { - ++txt; - --length; - } - continue; // Check if there is something else to handle... - } else { - // There is just an icon displayed on a full line. - break; + // Is there anything to display on this line? + if (length == 0) { + lines[i] = NULL; + lengths[i] = 0; + continue; } - } else { - if (extra_byte >= FIRST_STRING_BUFFER && - extra_byte <= LAST_STRING_BUFFER) { - // WARNING: if the string buffer contain an escape sequence to a - // string buffer, then we'll have an infinite loop! => Avoid that... - if (string_buffer) { - // Don't recursively parse string buffers! - txt = NULL; - length = 0; - break; - } - - // There is a string buffer, here => update txt to point on it: - txt = get_string_buffer(extra_byte); - // We have just switched from txt to string buffer => offset=0. - // (G_ux.layout_paging.offsets[i] is relative to original txt ptr) - // (G_ux.layout_paging.lengths[i] is related to string buffer) - // (G_ux.layout_paging.offsets[>i] are relative to string buffer) - // Use that string buffer for next lines on this page: - string_buffer = txt; - // Check for an escape sequence at the beginning of the string buffer: - continue; - - } else { // This is not an icon nor a screen buffer...ignore it! - txt = NULL; - length = 0; - break; + if (string_buffer) { + txt = string_buffer; + } + else if (text) { + txt = STRPIC(text); + } + else { + txt = G_ux.externalText; + } + // Take in account offset which is relative to txt ptr: + txt += G_ux.layout_paging.offsets[i]; + + // Check if this line starts with an escape sequence: + while (txt && txt[0] == '\e') { + // There is at least one more byte which is readable. + // (even if it is the end of the string, it contains '\0') + unsigned short extra_byte = (unsigned char) txt[1]; + // Is it an icon? + if (extra_byte >= FIRST_GLYPHS_ICON && extra_byte <= LAST_GLYPHS_ICON) { + // Does this line contain a 'left side icon'? + // If there is only an icon, then it is displayed on a full line. + // If there are text after the icon, it is displayed on left side. + // (=> This is what userid 0x0F is about!!) + if (length > 2) { + // This is a side icon => update icon_details ptr: + icon_details = get_glyphs_icon(extra_byte); + // Skip the side icon related bytes => update txt ptr & length: + txt += 2; + length -= 2; + // Skip all spaces characters after the side icon related bytes: + while (*txt == ' ' && length) { + ++txt; + --length; + } + continue; // Check if there is something else to handle... + } + else { + // There is just an icon displayed on a full line. + break; + } + } + else { + if (extra_byte >= FIRST_STRING_BUFFER && extra_byte <= LAST_STRING_BUFFER) { + // WARNING: if the string buffer contain an escape sequence to a + // string buffer, then we'll have an infinite loop! => Avoid that... + if (string_buffer) { + // Don't recursively parse string buffers! + txt = NULL; + length = 0; + break; + } + + // There is a string buffer, here => update txt to point on it: + txt = get_string_buffer(extra_byte); + // We have just switched from txt to string buffer => offset=0. + // (G_ux.layout_paging.offsets[i] is relative to original txt ptr) + // (G_ux.layout_paging.lengths[i] is related to string buffer) + // (G_ux.layout_paging.offsets[>i] are relative to string buffer) + // Use that string buffer for next lines on this page: + string_buffer = txt; + // Check for an escape sequence at the beginning of the string buffer: + continue; + } + else { // This is not an icon nor a screen buffer...ignore it! + txt = NULL; + length = 0; + break; + } + } } - } + // Store text pointer & length for this line: + lines[i] = txt; + lengths[i] = length; } - // Store text pointer & length for this line: - lines[i] = txt; - lengths[i] = length; - } - // Return a pointer to the side icon, if there is one on this page: - return icon_details; + // Return a pointer to the side icon, if there is one on this page: + return icon_details; } // ============================================================================= -const bagl_element_t* ux_layout_pages_prepro_common(const bagl_element_t* element, - const char* text) { - const char *lines[UX_LAYOUT_PAGES_LINE_COUNT]; - unsigned short lengths[UX_LAYOUT_PAGES_LINE_COUNT]; +const bagl_element_t *ux_layout_pages_prepro_common(const bagl_element_t *element, const char *text) +{ + const char *lines[UX_LAYOUT_PAGES_LINE_COUNT]; + unsigned short lengths[UX_LAYOUT_PAGES_LINE_COUNT]; - // copy element before any mod - memmove(&G_ux.tmp_element, element, sizeof(bagl_element_t)); + // copy element before any mod + memmove(&G_ux.tmp_element, element, sizeof(bagl_element_t)); - switch (element->component.userid) { - case 0x01: - // no step before AND no pages before - if (ux_flow_is_first() && G_ux.layout_paging.current == 0) { - return NULL; - } - break; + switch (element->component.userid) { + case 0x01: + // no step before AND no pages before + if (ux_flow_is_first() && G_ux.layout_paging.current == 0) { + return NULL; + } + break; - case 0x02: - if (ux_flow_is_last() && G_ux.layout_paging.current == G_ux.layout_paging.count -1 ) { - return NULL; - } - break; - - // Do we have to display 14x14 Icon on the left side, vertically centered? - case 0x0F: - case 0x1F: { - // Check all lines on this page to see if there is an icon on the side: - const bagl_icon_details_t *icon_side_details = update_lines_length(text, - lines, - lengths); - if (icon_side_details != NULL) { - G_ux.tmp_element.text = (const void *)icon_side_details; - return &G_ux.tmp_element; - } - // There is no 14x14 icon to display on the side. - return NULL; - } - // Up to 4 lines of text (can be mixed with one centered 14x14 Icon): - case 0x10: - case 0x11: - case 0x12: - case 0x13: - case 0x20: - case 0x21: - case 0x22: - case 0x23: - { - unsigned short lineidx = element->component.userid&0xF; - // Check if there is something to display on this line: - if (lineidx >= UX_LAYOUT_PAGES_LINE_COUNT || - G_ux.layout_paging.lengths[lineidx] == 0) { - return NULL; - } - // Check all lines on this page and update lines & lengths information: - // (if icon_side_details != NULL => there is an icon on left side) - const bagl_icon_details_t *icon_side_details = update_lines_length(text, - lines, - lengths); - G_ux.tmp_element.component.font_id = G_ux.layout_paging.fond_ids[lineidx]; - // When the icon is displayed on left side, text is left aligned: - if (icon_side_details != NULL) { - G_ux.tmp_element.component.font_id |= BAGL_FONT_ALIGNMENT_LEFT; - } else { - G_ux.tmp_element.component.font_id |= BAGL_FONT_ALIGNMENT_CENTER; - } - // Let's eat a little bit more vertical space on LNX: -#if (BAGL_HEIGHT==64) - short y_margin=BAGL_HEIGHT-FONT_HEIGHT; // Start at 52 -#endif //(BAGL_HEIGHT==64) - unsigned short nb_lines= 0; // Number of lines displayed in this screen - short y_coord = 0; // Y coordinate for this element - short x_coord = G_ux.tmp_element.component.x; - unsigned short used_height=0; // Number of vertical pixels used - - // Find at which X,Y coordinates this line have to be displayed: - // (we need to scan all lines...) - for (int i=0; i < UX_LAYOUT_PAGES_LINE_COUNT; i++) { - unsigned short length; - const char *txt; - - // Skip that line if it doesn't contain anything: - if ((length=lengths[i]) == 0 || (txt = lines[i]) == NULL) { - continue; - } - // By default consider this line will contain text => use font height - unsigned short height = FONT_HEIGHT; - - // If there is an icon displayed on the left side, adjust xcoord and - // available width of ALL lines: - if (icon_side_details != NULL) { - // The icon will be displayed when element->component.userid == 0x0F. - x_coord = BAGL_ICON_TEXT_XCOORD; // That's the X coord for PNN on LNS - G_ux.tmp_element.component.width = BAGL_ICON_TEXT_WIDTH; - } - // Does this line contain an icon? - // If yes it is the first characters in the string. - // If there is only the icon, then it is displayed on a full line. - // If there are text after the icon, it is displayed on left side. - // (This MUST HAVE BEEN handled before) - if (txt[0] == '\e') { - unsigned short extra_byte = (unsigned char)txt[1]; - // Is it really an icon? - if (extra_byte >= FIRST_GLYPHS_ICON && - extra_byte <= LAST_GLYPHS_ICON) { - // Be sure this icon have to be displayed here: - if (length == 2) { - // That line contain an icon => update height with correct value: - const bagl_icon_details_t *icon_details = get_glyphs_icon(extra_byte); - height = icon_details->height; - // If the icon is on current line, display it instead of text: - if (lineidx == i) { - G_ux.tmp_element.component.type = BAGL_ICON; - G_ux.tmp_element.component.icon_id = 0; - G_ux.tmp_element.text = (const char *)icon_details; - // Update x_coord, width & height using icon's width: - x_coord += (G_ux.tmp_element.component.width - icon_details->width) / 2; - G_ux.tmp_element.component.height = icon_details->height; - G_ux.tmp_element.component.width = icon_details->width; - } + case 0x02: + if (ux_flow_is_last() && G_ux.layout_paging.current == G_ux.layout_paging.count - 1) { + return NULL; + } + break; + + // Do we have to display 14x14 Icon on the left side, vertically centered? + case 0x0F: + case 0x1F: { + // Check all lines on this page to see if there is an icon on the side: + const bagl_icon_details_t *icon_side_details + = update_lines_length(text, lines, lengths); + if (icon_side_details != NULL) { + G_ux.tmp_element.text = (const void *) icon_side_details; + return &G_ux.tmp_element; } - } - } else if (lineidx == i) { - // Update G_ux.tmp_element.text value for the line we want to display: - SPRINTF(G_ux.layout_paging.line_buffer, "%.*s", - // avoid overflow - (unsigned int)(MIN(sizeof(G_ux.layout_paging.line_buffer)-1, length)), txt); - G_ux.tmp_element.text = G_ux.layout_paging.line_buffer; - // Don't forget to add Baseline for characters: - y_coord += FONT_BASELINE; + // There is no 14x14 icon to display on the side. + return NULL; } - if (i < lineidx) { - y_coord += height; + // Up to 4 lines of text (can be mixed with one centered 14x14 Icon): + case 0x10: + case 0x11: + case 0x12: + case 0x13: + case 0x20: + case 0x21: + case 0x22: + case 0x23: { + unsigned short lineidx = element->component.userid & 0xF; + // Check if there is something to display on this line: + if (lineidx >= UX_LAYOUT_PAGES_LINE_COUNT || G_ux.layout_paging.lengths[lineidx] == 0) { + return NULL; + } + // Check all lines on this page and update lines & lengths information: + // (if icon_side_details != NULL => there is an icon on left side) + const bagl_icon_details_t *icon_side_details + = update_lines_length(text, lines, lengths); + G_ux.tmp_element.component.font_id = G_ux.layout_paging.fond_ids[lineidx]; + // When the icon is displayed on left side, text is left aligned: + if (icon_side_details != NULL) { + G_ux.tmp_element.component.font_id |= BAGL_FONT_ALIGNMENT_LEFT; + } + else { + G_ux.tmp_element.component.font_id |= BAGL_FONT_ALIGNMENT_CENTER; + } + // Let's eat a little bit more vertical space on LNX: +#if (BAGL_HEIGHT == 64) + short y_margin = BAGL_HEIGHT - FONT_HEIGHT; // Start at 52 +#endif //(BAGL_HEIGHT==64) + unsigned short nb_lines = 0; // Number of lines displayed in this screen + short y_coord = 0; // Y coordinate for this element + short x_coord = G_ux.tmp_element.component.x; + unsigned short used_height = 0; // Number of vertical pixels used + + // Find at which X,Y coordinates this line have to be displayed: + // (we need to scan all lines...) + for (int i = 0; i < UX_LAYOUT_PAGES_LINE_COUNT; i++) { + unsigned short length; + const char *txt; + + // Skip that line if it doesn't contain anything: + if ((length = lengths[i]) == 0 || (txt = lines[i]) == NULL) { + continue; + } + // By default consider this line will contain text => use font height + unsigned short height = FONT_HEIGHT; + + // If there is an icon displayed on the left side, adjust xcoord and + // available width of ALL lines: + if (icon_side_details != NULL) { + // The icon will be displayed when element->component.userid == 0x0F. + x_coord = BAGL_ICON_TEXT_XCOORD; // That's the X coord for PNN on LNS + G_ux.tmp_element.component.width = BAGL_ICON_TEXT_WIDTH; + } + // Does this line contain an icon? + // If yes it is the first characters in the string. + // If there is only the icon, then it is displayed on a full line. + // If there are text after the icon, it is displayed on left side. + // (This MUST HAVE BEEN handled before) + if (txt[0] == '\e') { + unsigned short extra_byte = (unsigned char) txt[1]; + // Is it really an icon? + if (extra_byte >= FIRST_GLYPHS_ICON && extra_byte <= LAST_GLYPHS_ICON) { + // Be sure this icon have to be displayed here: + if (length == 2) { + // That line contain an icon => update height with correct value: + const bagl_icon_details_t *icon_details = get_glyphs_icon(extra_byte); + height = icon_details->height; + // If the icon is on current line, display it instead of text: + if (lineidx == i) { + G_ux.tmp_element.component.type = BAGL_ICON; + G_ux.tmp_element.component.icon_id = 0; + G_ux.tmp_element.text = (const char *) icon_details; + // Update x_coord, width & height using icon's width: + x_coord + += (G_ux.tmp_element.component.width - icon_details->width) / 2; + G_ux.tmp_element.component.height = icon_details->height; + G_ux.tmp_element.component.width = icon_details->width; + } + } + } + } + else if (lineidx == i) { + // Update G_ux.tmp_element.text value for the line we want to display: + SPRINTF( + G_ux.layout_paging.line_buffer, + "%.*s", + // avoid overflow + (unsigned int) (MIN(sizeof(G_ux.layout_paging.line_buffer) - 1, length)), + txt); + G_ux.tmp_element.text = G_ux.layout_paging.line_buffer; + // Don't forget to add Baseline for characters: + y_coord += FONT_BASELINE; + } + if (i < lineidx) { + y_coord += height; + } + used_height += height; + ++nb_lines; +#if (BAGL_HEIGHT == 64) + // Vertical margin depending on the number of lines displayed: + y_margin /= 2; // y_margin values will be 26,13,6,3 +#endif //(BAGL_HEIGHT==64) + } + // Y will depend on the number of lines displayed. +#if (BAGL_HEIGHT == 64) + y_coord += y_margin; + used_height += 2 * y_margin; +#endif //(BAGL_HEIGHT==64) + // Vertical padding (vertical space between each element) is: + // vertical_padding = (BAGL_HEIGHT - used_height) / (nb_lines + 1); + // So we can compute Y coordinate which will be: + y_coord += (((lineidx + 1) * (BAGL_HEIGHT - used_height)) + (nb_lines + 1) / 2) + / (nb_lines + 1); + // NB: previous computations provides almost same values than original + // ones, but we can replace them with manually fixed values if necessary. + G_ux.tmp_element.component.x = x_coord; + G_ux.tmp_element.component.y = y_coord; + break; } - used_height += height; - ++nb_lines; -#if (BAGL_HEIGHT==64) - // Vertical margin depending on the number of lines displayed: - y_margin /= 2; // y_margin values will be 26,13,6,3 -#endif //(BAGL_HEIGHT==64) - } - // Y will depend on the number of lines displayed. -#if (BAGL_HEIGHT==64) - y_coord += y_margin; - used_height += 2 * y_margin; -#endif //(BAGL_HEIGHT==64) - // Vertical padding (vertical space between each element) is: - // vertical_padding = (BAGL_HEIGHT - used_height) / (nb_lines + 1); - // So we can compute Y coordinate which will be: - y_coord += (((lineidx + 1) * (BAGL_HEIGHT - used_height)) + (nb_lines + 1)/2) / (nb_lines + 1); - // NB: previous computations provides almost same values than original - // ones, but we can replace them with manually fixed values if necessary. - G_ux.tmp_element.component.x = x_coord; - G_ux.tmp_element.component.y = y_coord; - break; } - } - return &G_ux.tmp_element; + return &G_ux.tmp_element; } // ============================================================================= -static bool is_loc_word_delim(unsigned char c) { - // return !((c >= 'a' && c <= 'z') - // || (c >= 'A' && c <= 'Z') - // || (c >= '0' && c <= '9')); - return c == ' ' || c == '\n' || c == '\b' || c == '\f' || c == '\e' || c == '-' || c == '_'; +static bool is_loc_word_delim(unsigned char c) +{ + // return !((c >= 'a' && c <= 'z') + // || (c >= 'A' && c <= 'Z') + // || (c >= '0' && c <= '9')); + return c == ' ' || c == '\n' || c == '\b' || c == '\f' || c == '\e' || c == '-' || c == '_'; } // return the number of pages to be displayed when current page to show is -1 -unsigned int ux_layout_pages_compute(const char* text_to_split, - unsigned int page_to_display, - ux_layout_paging_state_t* paging_state) { - bagl_font_id_e font_id; - - // reset length and offset of lines for this page - memset(paging_state->offsets, 0, sizeof(paging_state->offsets)); - memset(paging_state->lengths, 0, sizeof(paging_state->lengths)); - - // a page has been asked, but no page exists - if (page_to_display >= paging_state->count && page_to_display != (unsigned int)-1) { - return 0; - } - -#ifndef HAVE_FONTS - unsigned char paging_format; -#endif //HAVE_FONTS - // Regular font by default at the beginning of the first page: - unsigned char use_bold_font; - if (G_ux.layout_paging.format & PAGING_FORMAT_NB) { - use_bold_font = 1; - } else { - use_bold_font = 0; - } - // compute offset/length of text of each line for the current page - unsigned int page = 0; - unsigned int line = 0; - const char* start = (text_to_split ? STRPIC(text_to_split) : G_ux.externalText); - const char* start2 = start; - const char* end = start + strlen(start); - unsigned int string_buffer_mark_offset=(unsigned int)-1; - unsigned int string_buffer_mark_len = 0; - unsigned char string_buffer_id = 0; // By default, 0 => no string buffer - unsigned char icon_on_side = 0; - unsigned char extra_byte; - const char* page_start = start; - unsigned char page_use_bold_font = use_bold_font; - unsigned int string_buffer_start_page=(unsigned int)-1; - paging_state->string_buffer_id = string_buffer_id; - while (start < end) { - unsigned int len, icon_on_side_len; - unsigned int linew; - unsigned char c; -page_start_loop: - // When using UX_LOC_PAGING macro, first line contain the title on all pages - if (!line && G_ux.layout_paging.paging_title) { - paging_state->fond_ids[0] = BAGL_FONT_OPEN_SANS_REGULAR_11px; // By default - paging_state->lengths[0] = 1; // If 0 the line will be skipped - line = 1; +unsigned int ux_layout_pages_compute(const char *text_to_split, + unsigned int page_to_display, + ux_layout_paging_state_t *paging_state) +{ + bagl_font_id_e font_id; + + // reset length and offset of lines for this page + memset(paging_state->offsets, 0, sizeof(paging_state->offsets)); + memset(paging_state->lengths, 0, sizeof(paging_state->lengths)); + + // a page has been asked, but no page exists + if (page_to_display >= paging_state->count && page_to_display != (unsigned int) -1) { + return 0; } - len = icon_on_side_len = 0; - linew = 0; - c = 0; - // Skip all spaces characters at the beginning of the line: - while (*start == ' ' && (start+1) < end) { - ++start; +#ifndef HAVE_FONTS + unsigned char paging_format; +#endif // HAVE_FONTS + // Regular font by default at the beginning of the first page: + unsigned char use_bold_font; + if (G_ux.layout_paging.format & PAGING_FORMAT_NB) { + use_bold_font = 1; } - // If first character is \b, update bold state and remove it from the string - if (*start == '\b') { - use_bold_font ^= 1; - ++start; + else { + use_bold_font = 0; } - const char* last_word_delim = start; - // Initialise font_id at the beginning of each line depending on bold state: - if (use_bold_font) { - font_id = BAGL_FONT_OPEN_SANS_EXTRABOLD_11px; + // compute offset/length of text of each line for the current page + unsigned int page = 0; + unsigned int line = 0; + const char *start = (text_to_split ? STRPIC(text_to_split) : G_ux.externalText); + const char *start2 = start; + const char *end = start + strlen(start); + unsigned int string_buffer_mark_offset = (unsigned int) -1; + unsigned int string_buffer_mark_len = 0; + unsigned char string_buffer_id = 0; // By default, 0 => no string buffer + unsigned char icon_on_side = 0; + unsigned char extra_byte; + const char *page_start = start; + unsigned char page_use_bold_font = use_bold_font; + unsigned int string_buffer_start_page = (unsigned int) -1; + paging_state->string_buffer_id = string_buffer_id; + while (start < end) { + unsigned int len, icon_on_side_len; + unsigned int linew; + unsigned char c; + page_start_loop: + // When using UX_LOC_PAGING macro, first line contain the title on all pages + if (!line && G_ux.layout_paging.paging_title) { + paging_state->fond_ids[0] = BAGL_FONT_OPEN_SANS_REGULAR_11px; // By default + paging_state->lengths[0] = 1; // If 0 the line will be skipped + line = 1; + } + len = icon_on_side_len = 0; + linew = 0; + c = 0; + + // Skip all spaces characters at the beginning of the line: + while (*start == ' ' && (start + 1) < end) { + ++start; + } + // If first character is \b, update bold state and remove it from the string + if (*start == '\b') { + use_bold_font ^= 1; + ++start; + } + const char *last_word_delim = start; + // Initialise font_id at the beginning of each line depending on bold state: + if (use_bold_font) { + font_id = BAGL_FONT_OPEN_SANS_EXTRABOLD_11px; #ifndef HAVE_FONTS - paging_format = PAGING_FORMAT_NB; -#endif //HAVE_FONTS - } else { - font_id = BAGL_FONT_OPEN_SANS_REGULAR_11px; + paging_format = PAGING_FORMAT_NB; +#endif // HAVE_FONTS + } + else { + font_id = BAGL_FONT_OPEN_SANS_REGULAR_11px; #ifndef HAVE_FONTS - paging_format = PAGING_FORMAT_NN; -#endif //HAVE_FONTS - } - // not reached end of content - while (start + len < end - // line is not full - && (icon_on_side == 0 || linew <= BAGL_ICON_TEXT_WIDTH) && linew <= PIXEL_PER_LINE - // avoid display buffer overflow for each line - && len < (sizeof(G_ux.layout_paging.line_buffer)-1) - ) { - // ======================== - // Handle escape sequences: - // ========================= - // Check if this line starts with the escape character \e: - if (start[icon_on_side_len] == '\e') { - extra_byte = start[icon_on_side_len+1]; - // ---------------------------- - // Special case: string buffer: - // ---------------------------- - // If this is a string buffer, then restart parsing the string buffer: - if (extra_byte >= FIRST_STRING_BUFFER && extra_byte <= LAST_STRING_BUFFER) { - // Don't allow recursive string buffer! - if (string_buffer_id || !get_string_buffer(extra_byte)) { - // Ignore this escape sequence - if (!icon_on_side_len) { - start += 2; + paging_format = PAGING_FORMAT_NN; +#endif // HAVE_FONTS + } + // not reached end of content + while (start + len < end + // line is not full + && (icon_on_side == 0 || linew <= BAGL_ICON_TEXT_WIDTH) + && linew <= PIXEL_PER_LINE + // avoid display buffer overflow for each line + && len < (sizeof(G_ux.layout_paging.line_buffer) - 1)) { + // ======================== + // Handle escape sequences: + // ========================= + // Check if this line starts with the escape character \e: + if (start[icon_on_side_len] == '\e') { + extra_byte = start[icon_on_side_len + 1]; + // ---------------------------- + // Special case: string buffer: + // ---------------------------- + // If this is a string buffer, then restart parsing the string buffer: + if (extra_byte >= FIRST_STRING_BUFFER && extra_byte <= LAST_STRING_BUFFER) { + // Don't allow recursive string buffer! + if (string_buffer_id || !get_string_buffer(extra_byte)) { + // Ignore this escape sequence + if (!icon_on_side_len) { + start += 2; + } + } + else { + // Store the string buffer mark offset/len from original string: + string_buffer_mark_offset = start - start2; + string_buffer_mark_len = icon_on_side_len; + string_buffer_start_page = page; + // If the string just contain \b + the string buffer, switch now! + if (string_buffer_mark_offset == 1 && start2[0] == '\b') { + string_buffer_mark_offset = 0; + } + string_buffer_id = extra_byte; + // Get String buffer addr: + start = get_string_buffer(extra_byte); + start2 = start; + end = start + strlen(start); + } + // Just continue parsing starting from the same line, but with new text buffer: + goto page_start_loop; + } + // Currently, escape character use just one additional byte. + // If next character is '\n' or '\f' or '\0' we'll remove it and store 2 bytes: + // (this mean we was dealing with a full line icon) + // ----------------------------- + // Special case: full line icon: + // ----------------------------- + if (start[icon_on_side_len + 2] == '\n' || start[icon_on_side_len + 2] == '\f' + || start[icon_on_side_len + 2] == '\0') { + c = start[icon_on_side_len + 2]; + len = icon_on_side_len + 3; + break; + } + // ----------------------------- + // Special case: left side icon: + // ----------------------------- + // Otherwise, we continue adding following characters to that string. + // Check if line != 0 to restart scanning at line 0 with icon_on_side set! + if (!icon_on_side && line) { + line = 0; + icon_on_side = 1; + start = page_start; + end = start + strlen(start); + // If we switched to a string buffer on this page, reset start2: + if (string_buffer_start_page != (unsigned int) -1 + && string_buffer_start_page == page) { + start2 = (text_to_split ? STRPIC(text_to_split) : G_ux.externalText); + string_buffer_start_page = (unsigned int) -1; + paging_state->string_buffer_id = string_buffer_id = 0; + string_buffer_mark_offset = (unsigned int) -1; + string_buffer_mark_len = 0; + } + use_bold_font = page_use_bold_font; + // reset length and offset of lines for this page + if (page_to_display == page) { + memset(paging_state->offsets, 0, sizeof(paging_state->offsets)); + memset(paging_state->lengths, 0, sizeof(paging_state->lengths)); + } + goto page_start_loop; + } + icon_on_side = 1; + len += 2; + // Skip all spaces characters after the icon on side bytes: + while (start[len] == ' ') { + ++len; + } + // Be able to check \e after some icon on the side bytes! + icon_on_side_len = len; + // --------------------------------------------------------- + // Special case: string buffer right after a left side icon: + // --------------------------------------------------------- + continue; + // ================================= + // End of escape sequences handling: + // ================================= } - } - else { - // Store the string buffer mark offset/len from original string: - string_buffer_mark_offset = start - start2; - string_buffer_mark_len = icon_on_side_len; - string_buffer_start_page = page; - // If the string just contain \b + the string buffer, switch now! - if (string_buffer_mark_offset == 1 && start2[0] == '\b') { - string_buffer_mark_offset = 0; + // compute new line length +#ifdef HAVE_FONTS + linew = bagl_compute_line_width(font_id, 0, start, len + 1, BAGL_ENCODING_DEFAULT); +#else // HAVE_FONTS + linew = se_compute_line_width_light(start, len + 1, paging_format); +#endif // HAVE_FONTS + // if (start[len] ) + if ((icon_on_side != 0 && linew > BAGL_ICON_TEXT_WIDTH) || linew > PIXEL_PER_LINE) { + // we got a full line + break; + } + c = start[len]; + if (is_loc_word_delim(c)) { + last_word_delim = &start[len]; + } + len++; + // New line, don't go further + if (c == '\n' || c == '\f') { + break; } - string_buffer_id = extra_byte; - // Get String buffer addr: - start = get_string_buffer(extra_byte); - start2 = start; - end = start + strlen(start); - } - // Just continue parsing starting from the same line, but with new text buffer: - goto page_start_loop; - } - // Currently, escape character use just one additional byte. - // If next character is '\n' or '\f' or '\0' we'll remove it and store 2 bytes: - // (this mean we was dealing with a full line icon) - // ----------------------------- - // Special case: full line icon: - // ----------------------------- - if (start[icon_on_side_len+2] == '\n' || - start[icon_on_side_len+2] == '\f' || - start[icon_on_side_len+2] == '\0') { - c = start[icon_on_side_len+2]; - len = icon_on_side_len+3; - break; } - // ----------------------------- - // Special case: left side icon: - // ----------------------------- - // Otherwise, we continue adding following characters to that string. - // Check if line != 0 to restart scanning at line 0 with icon_on_side set! - if (!icon_on_side && line) { - line = 0; - icon_on_side = 1; - start = page_start; - end = start + strlen(start); - // If we switched to a string buffer on this page, reset start2: - if (string_buffer_start_page !=(unsigned int)-1 - && string_buffer_start_page == page) { - start2 = (text_to_split ? STRPIC(text_to_split) : G_ux.externalText); - string_buffer_start_page=(unsigned int)-1; - paging_state->string_buffer_id = string_buffer_id = 0; - string_buffer_mark_offset=(unsigned int)-1; - string_buffer_mark_len = 0; - } - use_bold_font = page_use_bold_font; - // reset length and offset of lines for this page - if (page_to_display == page) { - memset(paging_state->offsets, 0, sizeof(paging_state->offsets)); - memset(paging_state->lengths, 0, sizeof(paging_state->lengths)); - } - goto page_start_loop; + + // if not splitting line onto a word delimiter, then cut at the previous word_delim, adjust + // len accordingly (and a word delim has been found already) + if (start + len < end && last_word_delim != start && len) { + // if line split within a word + if ((!is_loc_word_delim(start[len - 1]) && !is_loc_word_delim(start[len]))) { + len = last_word_delim - start; + } } - icon_on_side = 1; - len += 2; - // Skip all spaces characters after the icon on side bytes: - while (start[len] == ' ') { - ++len; + + // Update boldness: parse text and toggle boldness if needed: + for (unsigned int i = 0; i < len; i++) { + if (start[i] == '\b') { + use_bold_font ^= 1; + } } - // Be able to check \e after some icon on the side bytes! - icon_on_side_len = len; - // --------------------------------------------------------- - // Special case: string buffer right after a left side icon: - // --------------------------------------------------------- - continue; - // ================================= - // End of escape sequences handling: - // ================================= - } - // compute new line length -#ifdef HAVE_FONTS - linew = bagl_compute_line_width(font_id, 0, start, len+1, BAGL_ENCODING_DEFAULT); -#else // HAVE_FONTS - linew = se_compute_line_width_light(start, len + 1, paging_format); -#endif //HAVE_FONTS - //if (start[len] ) - if ((icon_on_side != 0 && linew > BAGL_ICON_TEXT_WIDTH) || linew > PIXEL_PER_LINE) { - // we got a full line - break; - } - c = start[len]; - if (is_loc_word_delim(c)) { - last_word_delim = &start[len]; - } - len++; - // New line, don't go further - if (c == '\n' || c == '\f') { - break; - } - } + // fill up the paging structure + if (page_to_display != (unsigned int) -1 && page_to_display == page + && page_to_display < paging_state->count) { + // If we just switched to a string buffer, keep the offset from original string: + if (string_buffer_mark_offset != (unsigned int) -1) { + paging_state->offsets[line] = string_buffer_mark_offset; + } + else { + paging_state->offsets[line] = start - start2; + } + // Store string buffer id if we are not in the initial page or if there + // is only the string buffer to display in that page + if (string_buffer_start_page != (unsigned int) -1 + && (string_buffer_start_page < page + || (string_buffer_start_page == page && string_buffer_mark_offset == 0))) { + paging_state->string_buffer_id = string_buffer_id; // Contain 0xB1, 0xB2, etc + } + // Remove the '\n' or '\f' from the string (=> no need to handle it anymore!) + if (c == '\n' || c == '\f' || c == '\0') { + paging_state->lengths[line] = len - 1 + string_buffer_mark_len; + } + else { + paging_state->lengths[line] = len + string_buffer_mark_len; + } + string_buffer_mark_offset = (unsigned int) -1; + string_buffer_mark_len = 0; - // if not splitting line onto a word delimiter, then cut at the previous word_delim, adjust len accordingly (and a word delim has been found already) - if (start + len < end && last_word_delim != start && len) { - // if line split within a word - if ((!is_loc_word_delim(start[len-1]) && !is_loc_word_delim(start[len]))) { - len = last_word_delim - start; - } - } + paging_state->fond_ids[line] = font_id; - // Update boldness: parse text and toggle boldness if needed: - for (unsigned int i=0; i < len; i++) { - if (start[i] == '\b') { - use_bold_font ^= 1; - } - } - // fill up the paging structure - if (page_to_display != (unsigned int)-1 && page_to_display == page && page_to_display < paging_state->count) { - // If we just switched to a string buffer, keep the offset from original string: - if (string_buffer_mark_offset != (unsigned int)-1) { - paging_state->offsets[line] = string_buffer_mark_offset; - } else { - paging_state->offsets[line] = start - start2; - } - // Store string buffer id if we are not in the initial page or if there - // is only the string buffer to display in that page - if (string_buffer_start_page !=(unsigned int)-1 && - (string_buffer_start_page < page || (string_buffer_start_page == page && string_buffer_mark_offset == 0))) { - paging_state->string_buffer_id = string_buffer_id; // Contain 0xB1, 0xB2, etc - } - // Remove the '\n' or '\f' from the string (=> no need to handle it anymore!) - if (c == '\n' || c == '\f' || c == '\0') { - paging_state->lengths[line] = len - 1 + string_buffer_mark_len; - } else { - paging_state->lengths[line] = len + string_buffer_mark_len; - } - string_buffer_mark_offset = (unsigned int)-1; - string_buffer_mark_len = 0; - - paging_state->fond_ids[line] = font_id; - - // won't compute all pages, we reached the one to display + // won't compute all pages, we reached the one to display #if UX_LAYOUT_PAGES_LINE_COUNT > 1 - if (line >= UX_LAYOUT_PAGES_LINE_COUNT-1) -#endif //UX_LAYOUT_PAGES_LINE_COUNT - { - return 1; - } - } + if (line >= UX_LAYOUT_PAGES_LINE_COUNT - 1) +#endif // UX_LAYOUT_PAGES_LINE_COUNT + { + return 1; + } + } - // prepare for next line - start += len; + // prepare for next line + start += len; - // skip to next line/page - line++; + // skip to next line/page + line++; - // Do we want to jump to next page? - if (c == '\f' || ( + // Do we want to jump to next page? + if (c == '\f' + || ( #if UX_LAYOUT_PAGES_LINE_COUNT > 1 - line >= UX_LAYOUT_PAGES_LINE_COUNT && -#endif //UX_LAYOUT_PAGES_LINE_COUNT - start < end)) { - page++; - line = 0; - icon_on_side = 0; - page_start = start; - string_buffer_mark_offset = (unsigned int)-1; - string_buffer_mark_len = 0; - page_use_bold_font = use_bold_font; + line >= UX_LAYOUT_PAGES_LINE_COUNT && +#endif // UX_LAYOUT_PAGES_LINE_COUNT + start < end)) { + page++; + line = 0; + icon_on_side = 0; + page_start = start; + string_buffer_mark_offset = (unsigned int) -1; + string_buffer_mark_len = 0; + page_use_bold_font = use_bold_font; + } } - } - // return total number of pages detected - return page+1; + // return total number of pages detected + return page + 1; } // ============================================================================= -void ux_layout_pages_display_init(const char* text) { - // Compute all UX_LOC_PAGE stuff into G_ux.layout_paging - G_ux.layout_paging.current = 0; - G_ux.layout_paging.count = 1; - G_ux.layout_paging.paging_title = 0; - G_ux.layout_paging.format = PAGING_FORMAT_NN; - // request offsets and lengths of lines for the current page - ux_layout_pages_compute(text, G_ux.layout_paging.current, &G_ux.layout_paging); +void ux_layout_pages_display_init(const char *text) +{ + // Compute all UX_LOC_PAGE stuff into G_ux.layout_paging + G_ux.layout_paging.current = 0; + G_ux.layout_paging.count = 1; + G_ux.layout_paging.paging_title = 0; + G_ux.layout_paging.format = PAGING_FORMAT_NN; + // request offsets and lengths of lines for the current page + ux_layout_pages_compute(text, G_ux.layout_paging.current, &G_ux.layout_paging); } -const bagl_element_t* ux_layout_pages_display_element(const bagl_element_t* element, - const char* text) { - - return ux_layout_pages_prepro_common(element, text); +const bagl_element_t *ux_layout_pages_display_element(const bagl_element_t *element, + const char *text) +{ + return ux_layout_pages_prepro_common(element, text); } // ============================================================================= // redisplay current page -void ux_layout_pages_redisplay_common(unsigned int stack_slot, const char* text, button_push_callback_t button_callback, bagl_element_callback_t prepro) { - ux_stack_slot_t* slot = &G_ux.stack[stack_slot]; - - slot->element_arrays[0].element_array = ux_layout_pages_elements; - slot->element_arrays[0].element_array_count = ARRAYLEN(ux_layout_pages_elements); - slot->element_arrays_count = 1; - - // request offsets and lengths of lines for the current page - ux_layout_pages_compute(text, - G_ux.layout_paging.current, - &G_ux.layout_paging); - - slot->screen_before_element_display_callback = prepro; - slot->button_push_callback = button_callback; - ux_stack_display(stack_slot); +void ux_layout_pages_redisplay_common(unsigned int stack_slot, + const char *text, + button_push_callback_t button_callback, + bagl_element_callback_t prepro) +{ + ux_stack_slot_t *slot = &G_ux.stack[stack_slot]; + + slot->element_arrays[0].element_array = ux_layout_pages_elements; + slot->element_arrays[0].element_array_count = ARRAYLEN(ux_layout_pages_elements); + slot->element_arrays_count = 1; + + // request offsets and lengths of lines for the current page + ux_layout_pages_compute(text, G_ux.layout_paging.current, &G_ux.layout_paging); + + slot->screen_before_element_display_callback = prepro; + slot->button_push_callback = button_callback; + ux_stack_display(stack_slot); } -static const bagl_element_t* ux_layout_pages_prepro_by_addr(const bagl_element_t* element) { - // don't display if null - const void *params = ux_stack_get_current_step_params(); - if (NULL == params) { - return NULL; - } - const char* text; +static const bagl_element_t *ux_layout_pages_prepro_by_addr(const bagl_element_t *element) +{ + // don't display if null + const void *params = ux_stack_get_current_step_params(); + if (NULL == params) { + return NULL; + } + const char *text; #if defined(HAVE_INDEXED_STRINGS) - text = get_ux_loc_string(((const ux_loc_layout_params_t*)params)->index); -#else //defined(HAVE_INDEXED_STRINGS) - text = ((const ux_layout_pages_params_t*)params)->text; -#endif //defined(HAVE_INDEXED_STRINGS) - return ux_layout_pages_prepro_common(element, text); + text = get_ux_loc_string(((const ux_loc_layout_params_t *) params)->index); +#else // defined(HAVE_INDEXED_STRINGS) + text = ((const ux_layout_pages_params_t *) params)->text; +#endif // defined(HAVE_INDEXED_STRINGS) + return ux_layout_pages_prepro_common(element, text); } -unsigned int ux_layout_pages_button_callback_by_addr(unsigned int button_mask, unsigned int button_mask_counter); -unsigned int ux_loc_layout_paging_button_callback_by_addr(unsigned int button_mask, unsigned int button_mask_counter); - -void ux_layout_pages_redisplay_by_addr(unsigned int stack_slot) { - const char* text; - const void *params = ux_stack_get_current_step_params(); - if (NULL == params) { - return; - } +unsigned int ux_layout_pages_button_callback_by_addr(unsigned int button_mask, + unsigned int button_mask_counter); +unsigned int ux_loc_layout_paging_button_callback_by_addr(unsigned int button_mask, + unsigned int button_mask_counter); + +void ux_layout_pages_redisplay_by_addr(unsigned int stack_slot) +{ + const char *text; + const void *params = ux_stack_get_current_step_params(); + if (NULL == params) { + return; + } #if defined(HAVE_INDEXED_STRINGS) - text = get_ux_loc_string(((const ux_loc_layout_params_t*)params)->index); -#else //defined(HAVE_INDEXED_STRINGS) - text = ((const ux_layout_pages_params_t*)params)->text; -#endif //defined(HAVE_INDEXED_STRINGS) - ux_layout_pages_redisplay_common(stack_slot, text, ux_layout_pages_button_callback_by_addr, ux_layout_pages_prepro_by_addr); + text = get_ux_loc_string(((const ux_loc_layout_params_t *) params)->index); +#else // defined(HAVE_INDEXED_STRINGS) + text = ((const ux_layout_pages_params_t *) params)->text; +#endif // defined(HAVE_INDEXED_STRINGS) + ux_layout_pages_redisplay_common( + stack_slot, text, ux_layout_pages_button_callback_by_addr, ux_layout_pages_prepro_by_addr); } -static const bagl_element_t* ux_loc_layout_paging_prepro_by_addr(const bagl_element_t* element) { - // don't display if null - const void *params = ux_stack_get_current_step_params(); - if (NULL == params) { - return NULL; - } - const char* text; - - // As 0 mean it's not a UX_LOC_PAGING (due to all the memset layout_paging) - // Store index value + 1 - G_ux.layout_paging.paging_title = ((const ux_loc_layout_params_t*)params)->index+1; - text = get_ux_loc_string(G_ux.layout_paging.paging_title-1+1); - return ux_layout_pages_prepro_common(element, text); +static const bagl_element_t *ux_loc_layout_paging_prepro_by_addr(const bagl_element_t *element) +{ + // don't display if null + const void *params = ux_stack_get_current_step_params(); + if (NULL == params) { + return NULL; + } + const char *text; + + // As 0 mean it's not a UX_LOC_PAGING (due to all the memset layout_paging) + // Store index value + 1 + G_ux.layout_paging.paging_title = ((const ux_loc_layout_params_t *) params)->index + 1; + text = get_ux_loc_string(G_ux.layout_paging.paging_title - 1 + 1); + return ux_layout_pages_prepro_common(element, text); } -void ux_loc_layout_paging_redisplay_by_addr(unsigned int stack_slot) { - const char* text; - const void *params = ux_stack_get_current_step_params(); - if (NULL == params) { - return; - } - // As 0 mean it's not a UX_LOC_PAGING (due to all the memset layout_paging) - // Store index value + 1 - G_ux.layout_paging.paging_title = ((const ux_loc_layout_params_t*)params)->index+1; - text = get_ux_loc_string(G_ux.layout_paging.paging_title-1+1); - ux_layout_pages_redisplay_common(stack_slot, text, ux_loc_layout_paging_button_callback_by_addr, ux_loc_layout_paging_prepro_by_addr); +void ux_loc_layout_paging_redisplay_by_addr(unsigned int stack_slot) +{ + const char *text; + const void *params = ux_stack_get_current_step_params(); + if (NULL == params) { + return; + } + // As 0 mean it's not a UX_LOC_PAGING (due to all the memset layout_paging) + // Store index value + 1 + G_ux.layout_paging.paging_title = ((const ux_loc_layout_params_t *) params)->index + 1; + text = get_ux_loc_string(G_ux.layout_paging.paging_title - 1 + 1); + ux_layout_pages_redisplay_common(stack_slot, + text, + ux_loc_layout_paging_button_callback_by_addr, + ux_loc_layout_paging_prepro_by_addr); } // Function located in ux_layout_paging.c -unsigned int ux_layout_paging_button_callback_common(unsigned int button_mask, unsigned int button_mask_counter, ux_layout_paging_redisplay_t redisplay); - -unsigned int ux_loc_layout_paging_button_callback_by_addr(unsigned int button_mask, unsigned int button_mask_counter) { - return ux_layout_paging_button_callback_common(button_mask, button_mask_counter, ux_loc_layout_paging_redisplay_by_addr); +unsigned int ux_layout_paging_button_callback_common(unsigned int button_mask, + unsigned int button_mask_counter, + ux_layout_paging_redisplay_t redisplay); + +unsigned int ux_loc_layout_paging_button_callback_by_addr(unsigned int button_mask, + unsigned int button_mask_counter) +{ + return ux_layout_paging_button_callback_common( + button_mask, button_mask_counter, ux_loc_layout_paging_redisplay_by_addr); } -unsigned int ux_layout_pages_button_callback_by_addr(unsigned int button_mask, unsigned int button_mask_counter) { - return ux_layout_paging_button_callback_common(button_mask, button_mask_counter, ux_layout_pages_redisplay_by_addr); +unsigned int ux_layout_pages_button_callback_by_addr(unsigned int button_mask, + unsigned int button_mask_counter) +{ + return ux_layout_paging_button_callback_common( + button_mask, button_mask_counter, ux_layout_pages_redisplay_by_addr); } -void ux_layout_pages_init(unsigned int stack_slot) { - const char* text; - const void *params = ux_stack_get_step_params(stack_slot); +void ux_layout_pages_init(unsigned int stack_slot) +{ + const char *text; + const void *params = ux_stack_get_step_params(stack_slot); - G_ux.layout_paging.format = PAGING_FORMAT_NN; // By default - G_ux.layout_paging.paging_title = 0; // 0 mean it's not a UX_LOC_PAGING + G_ux.layout_paging.format = PAGING_FORMAT_NN; // By default + G_ux.layout_paging.paging_title = 0; // 0 mean it's not a UX_LOC_PAGING #if defined(HAVE_INDEXED_STRINGS) - text = get_ux_loc_string(((const ux_loc_layout_params_t*)params)->index); -#else //defined(HAVE_INDEXED_STRINGS) - text = ((const ux_layout_pages_params_t*)params)->text; -#endif //defined(HAVE_INDEXED_STRINGS) - ux_layout_pages_init_common(stack_slot, text, ux_layout_pages_redisplay_by_addr); + text = get_ux_loc_string(((const ux_loc_layout_params_t *) params)->index); +#else // defined(HAVE_INDEXED_STRINGS) + text = ((const ux_layout_pages_params_t *) params)->text; +#endif // defined(HAVE_INDEXED_STRINGS) + ux_layout_pages_init_common(stack_slot, text, ux_layout_pages_redisplay_by_addr); } -void ux_loc_layout_pages_init(unsigned int stack_slot) { - ux_layout_pages_init(stack_slot); +void ux_loc_layout_pages_init(unsigned int stack_slot) +{ + ux_layout_pages_init(stack_slot); } -void ux_loc_layout_paging_init(unsigned int stack_slot) { - const char *text; - const void *params = ux_stack_get_step_params(stack_slot); - - G_ux.layout_paging.format = PAGING_FORMAT_NN; // By default - // As 0 mean it's not a UX_LOC_PAGING (due to all the memset layout_paging) - // Store index value + 1 - G_ux.layout_paging.paging_title = ((const ux_loc_layout_params_t*)params)->index+1; - text = get_ux_loc_string(G_ux.layout_paging.paging_title-1+1); - ux_layout_pages_init_common(stack_slot, text, ux_loc_layout_paging_redisplay_by_addr); +void ux_loc_layout_paging_init(unsigned int stack_slot) +{ + const char *text; + const void *params = ux_stack_get_step_params(stack_slot); + + G_ux.layout_paging.format = PAGING_FORMAT_NN; // By default + // As 0 mean it's not a UX_LOC_PAGING (due to all the memset layout_paging) + // Store index value + 1 + G_ux.layout_paging.paging_title = ((const ux_loc_layout_params_t *) params)->index + 1; + text = get_ux_loc_string(G_ux.layout_paging.paging_title - 1 + 1); + ux_layout_pages_init_common(stack_slot, text, ux_loc_layout_paging_redisplay_by_addr); } -#endif // (defined HAVE_BOLOS || defined(BUILD_PNG)) - -void ux_layout_pages_init_common(unsigned int stack_slot, const char* text, ux_layout_paging_redisplay_t redisplay) { - - // At this very moment, we don't want to get rid of the format nor paging_title, so - // keep the one which has just been set (in case of direction backward or forward). - unsigned int backup_format = G_ux.layout_paging.format; - unsigned int backup_title = G_ux.layout_paging.paging_title; - - // depending flow browsing direction, select the correct page to display - switch(ux_flow_direction()) { - case FLOW_DIRECTION_BACKWARD: - ux_layout_paging_reset(); - // ask the paging to start at the last page. - // This step must be performed after the 'ux_layout_paging_reset' call, - // thus we cannot mutualize the call with the one in the 'forward' case. - G_ux.layout_paging.current = (unsigned int)-1; - break; - case FLOW_DIRECTION_FORWARD: - // open the first page - ux_layout_paging_reset(); - break; - case FLOW_DIRECTION_START: - // shall already be at the first page - break; - } - - G_ux.layout_paging.format = backup_format; - G_ux.layout_paging.paging_title = backup_title; - - // store params - ux_stack_init(stack_slot); - - // compute number of chars to display from the params complete string - if ((text == NULL) && (G_ux.externalText == NULL)) { - text = ""; // empty string to avoid disrupting the ux flow. - } - - // count total number of pages - G_ux.layout_paging.count = ux_layout_pages_compute(text, (unsigned int)-1, &G_ux.layout_paging); // at least one page - - //PRINTF("%d pages needed for =>%s<=\n", G_ux.layout_paging.count, text); - if (G_ux.layout_paging.count == 0) { - ux_layout_paging_reset(); - } - - // if (start != end) { - // ux_layout_paging_reset(); - // } - - // perform displaying the last page as requested (-1UL in prevstep hook does this) - if (G_ux.layout_paging.count && G_ux.layout_paging.current > (G_ux.layout_paging.count-1)) { - G_ux.layout_paging.current = G_ux.layout_paging.count-1; - } - - redisplay(stack_slot); +#endif // (defined HAVE_BOLOS || defined(BUILD_PNG)) + +void ux_layout_pages_init_common(unsigned int stack_slot, + const char *text, + ux_layout_paging_redisplay_t redisplay) +{ + // At this very moment, we don't want to get rid of the format nor paging_title, so + // keep the one which has just been set (in case of direction backward or forward). + unsigned int backup_format = G_ux.layout_paging.format; + unsigned int backup_title = G_ux.layout_paging.paging_title; + + // depending flow browsing direction, select the correct page to display + switch (ux_flow_direction()) { + case FLOW_DIRECTION_BACKWARD: + ux_layout_paging_reset(); + // ask the paging to start at the last page. + // This step must be performed after the 'ux_layout_paging_reset' call, + // thus we cannot mutualize the call with the one in the 'forward' case. + G_ux.layout_paging.current = (unsigned int) -1; + break; + case FLOW_DIRECTION_FORWARD: + // open the first page + ux_layout_paging_reset(); + break; + case FLOW_DIRECTION_START: + // shall already be at the first page + break; + } + + G_ux.layout_paging.format = backup_format; + G_ux.layout_paging.paging_title = backup_title; + + // store params + ux_stack_init(stack_slot); + + // compute number of chars to display from the params complete string + if ((text == NULL) && (G_ux.externalText == NULL)) { + text = ""; // empty string to avoid disrupting the ux flow. + } + + // count total number of pages + G_ux.layout_paging.count = ux_layout_pages_compute( + text, (unsigned int) -1, &G_ux.layout_paging); // at least one page + + // PRINTF("%d pages needed for =>%s<=\n", G_ux.layout_paging.count, text); + if (G_ux.layout_paging.count == 0) { + ux_layout_paging_reset(); + } + + // if (start != end) { + // ux_layout_paging_reset(); + // } + + // perform displaying the last page as requested (-1UL in prevstep hook does this) + if (G_ux.layout_paging.count && G_ux.layout_paging.current > (G_ux.layout_paging.count - 1)) { + G_ux.layout_paging.current = G_ux.layout_paging.count - 1; + } + + redisplay(stack_slot); } -#endif // HAVE_BAGL -#endif //defined(HAVE_INDEXED_STRINGS) -#endif // HAVE_UX_FLOW +#endif // HAVE_BAGL +#endif // defined(HAVE_INDEXED_STRINGS) +#endif // HAVE_UX_FLOW diff --git a/lib_ux/src/ux_layout_paging.c b/lib_ux/src/ux_layout_paging.c index c692a155f..887b1078a 100644 --- a/lib_ux/src/ux_layout_paging.c +++ b/lib_ux/src/ux_layout_paging.c @@ -1,20 +1,20 @@ /******************************************************************************* -* Ledger Nano S - Secure firmware -* (c) 2022 Ledger -* -* Licensed under the Apache License, Version 2.0 (the "License"); -* you may not use this file except in compliance with the License. -* You may obtain a copy of the License at -* -* http://www.apache.org/licenses/LICENSE-2.0 -* -* Unless required by applicable law or agreed to in writing, software -* distributed under the License is distributed on an "AS IS" BASIS, -* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -* See the License for the specific language governing permissions and -* limitations under the License. -********************************************************************************/ + * Ledger Nano S - Secure firmware + * (c) 2022 Ledger + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT 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 "os_helpers.h" #include "os_math.h" @@ -36,7 +36,8 @@ */ #define LINE_FONT BAGL_FONT_OPEN_SANS_REGULAR_11px -#if (BAGL_WIDTH==128 && BAGL_HEIGHT==64) +#if (BAGL_WIDTH == 128 && BAGL_HEIGHT == 64) +// clang-format off static const bagl_element_t ux_layout_paging_elements[] = { // erase {{BAGL_RECTANGLE , 0x00, 0, 0, 128, 64, 0, 0, BAGL_FILL, 0x000000, 0xFFFFFF, 0, 0}, .text=NULL}, @@ -49,272 +50,313 @@ static const bagl_element_t ux_layout_paging_elements[] = { {{BAGL_LABELINE , 0x12, (128-PIXEL_PER_LINE)/2, 43, PIXEL_PER_LINE, 12, 0, 0, 0 , 0xFFFFFF, 0x000000, LINE_FONT|BAGL_FONT_ALIGNMENT_CENTER, 0 }, .text=NULL}, {{BAGL_LABELINE , 0x13, (128-PIXEL_PER_LINE)/2, 57, PIXEL_PER_LINE, 12, 0, 0, 0 , 0xFFFFFF, 0x000000, LINE_FONT|BAGL_FONT_ALIGNMENT_CENTER, 0 }, .text=NULL}, }; -#endif // (BAGL_WIDTH==128 && BAGL_HEIGHT==64) - -const bagl_element_t* ux_layout_paging_prepro_common(const bagl_element_t* element, - const char* title, - const char* text) { - - // copy element before any mod - memmove(&G_ux.tmp_element, element, sizeof(bagl_element_t)); - - switch (element->component.userid) { - case 0x01: - // no step before AND no pages before - if (ux_flow_is_first() && G_ux.layout_paging.current == 0) { - return NULL; - } - break; - - case 0x02: - if (ux_flow_is_last() && G_ux.layout_paging.current == G_ux.layout_paging.count -1 ) { - return NULL; - } - break; - - case 0x10: - // We set the boldness of the text. - // display - if (title) { - SPRINTF(G_ux.string_buffer, (G_ux.layout_paging.count>1)?"%s (%d/%d)":"%s", STRPIC(title), G_ux.layout_paging.current+1, G_ux.layout_paging.count); - } - else { - SPRINTF(G_ux.string_buffer, "%d/%d", G_ux.layout_paging.current+1, G_ux.layout_paging.count); - } - - G_ux.tmp_element.component.font_id = ((G_ux.layout_paging.format & PAGING_FORMAT_BN) == PAGING_FORMAT_BN) ? - (BAGL_FONT_OPEN_SANS_EXTRABOLD_11px | BAGL_FONT_ALIGNMENT_CENTER) - : (BAGL_FONT_OPEN_SANS_REGULAR_11px | BAGL_FONT_ALIGNMENT_CENTER); - G_ux.tmp_element.text = G_ux.string_buffer; - break; - - case 0x11: - case 0x12: - case 0x13: { - unsigned int lineidx = (element->component.userid&0xF)-1; - if ( - lineidx < UX_LAYOUT_PAGING_LINE_COUNT && - G_ux.layout_paging.lengths[lineidx]) { - SPRINTF(G_ux.string_buffer, - "%.*s", - // avoid overflow - MIN(sizeof(G_ux.string_buffer)-1,G_ux.layout_paging.lengths[lineidx]), - (text ? STRPIC(text) : G_ux.externalText) + G_ux.layout_paging.offsets[lineidx]); - G_ux.tmp_element.text = G_ux.string_buffer; - - G_ux.tmp_element.component.font_id = ((G_ux.layout_paging.format & PAGING_FORMAT_NB) == PAGING_FORMAT_NB) ? - (BAGL_FONT_OPEN_SANS_EXTRABOLD_11px | BAGL_FONT_ALIGNMENT_CENTER) - : (BAGL_FONT_OPEN_SANS_REGULAR_11px | BAGL_FONT_ALIGNMENT_CENTER); - } - break; +// clang-format on +#endif // (BAGL_WIDTH==128 && BAGL_HEIGHT==64) + +const bagl_element_t *ux_layout_paging_prepro_common(const bagl_element_t *element, + const char *title, + const char *text) +{ + // copy element before any mod + memmove(&G_ux.tmp_element, element, sizeof(bagl_element_t)); + + switch (element->component.userid) { + case 0x01: + // no step before AND no pages before + if (ux_flow_is_first() && G_ux.layout_paging.current == 0) { + return NULL; + } + break; + + case 0x02: + if (ux_flow_is_last() && G_ux.layout_paging.current == G_ux.layout_paging.count - 1) { + return NULL; + } + break; + + case 0x10: + // We set the boldness of the text. + // display + if (title) { + SPRINTF(G_ux.string_buffer, + (G_ux.layout_paging.count > 1) ? "%s (%d/%d)" : "%s", + STRPIC(title), + G_ux.layout_paging.current + 1, + G_ux.layout_paging.count); + } + else { + SPRINTF(G_ux.string_buffer, + "%d/%d", + G_ux.layout_paging.current + 1, + G_ux.layout_paging.count); + } + + G_ux.tmp_element.component.font_id + = ((G_ux.layout_paging.format & PAGING_FORMAT_BN) == PAGING_FORMAT_BN) + ? (BAGL_FONT_OPEN_SANS_EXTRABOLD_11px | BAGL_FONT_ALIGNMENT_CENTER) + : (BAGL_FONT_OPEN_SANS_REGULAR_11px | BAGL_FONT_ALIGNMENT_CENTER); + G_ux.tmp_element.text = G_ux.string_buffer; + break; + + case 0x11: + case 0x12: + case 0x13: { + unsigned int lineidx = (element->component.userid & 0xF) - 1; + if (lineidx < UX_LAYOUT_PAGING_LINE_COUNT && G_ux.layout_paging.lengths[lineidx]) { + SPRINTF(G_ux.string_buffer, + "%.*s", + // avoid overflow + MIN(sizeof(G_ux.string_buffer) - 1, G_ux.layout_paging.lengths[lineidx]), + (text ? STRPIC(text) : G_ux.externalText) + + G_ux.layout_paging.offsets[lineidx]); + G_ux.tmp_element.text = G_ux.string_buffer; + + G_ux.tmp_element.component.font_id + = ((G_ux.layout_paging.format & PAGING_FORMAT_NB) == PAGING_FORMAT_NB) + ? (BAGL_FONT_OPEN_SANS_EXTRABOLD_11px | BAGL_FONT_ALIGNMENT_CENTER) + : (BAGL_FONT_OPEN_SANS_REGULAR_11px | BAGL_FONT_ALIGNMENT_CENTER); + } + break; + } } - } - return &G_ux.tmp_element; + return &G_ux.tmp_element; } -static const bagl_element_t* ux_layout_paging_prepro_by_addr(const bagl_element_t* element) { - // don't display if null - const void *params = ux_stack_get_current_step_params(); - if (NULL == params) { - return NULL; - } - const char* title; - const char* text; +static const bagl_element_t *ux_layout_paging_prepro_by_addr(const bagl_element_t *element) +{ + // don't display if null + const void *params = ux_stack_get_current_step_params(); + if (NULL == params) { + return NULL; + } + const char *title; + const char *text; #if defined(HAVE_INDEXED_STRINGS) - UX_LOC_STRINGS_INDEX index = ((const ux_loc_layout_params_t*)params)->index; - title = get_ux_loc_string(index); - text = get_ux_loc_string(index+1); -#else //defined(HAVE_INDEXED_STRINGS) - title = ((const ux_layout_paging_params_t*)params)->title; - text = ((const ux_layout_paging_params_t*)params)->text; -#endif //defined(HAVE_INDEXED_STRINGS) - return ux_layout_paging_prepro_common(element, title, text); + UX_LOC_STRINGS_INDEX index = ((const ux_loc_layout_params_t *) params)->index; + title = get_ux_loc_string(index); + text = get_ux_loc_string(index + 1); +#else // defined(HAVE_INDEXED_STRINGS) + title = ((const ux_layout_paging_params_t *) params)->title; + text = ((const ux_layout_paging_params_t *) params)->text; +#endif // defined(HAVE_INDEXED_STRINGS) + return ux_layout_paging_prepro_common(element, title, text); } // redisplay current page -void ux_layout_paging_redisplay_common(unsigned int stack_slot, const char* text, button_push_callback_t button_callback, bagl_element_callback_t prepro) { - bagl_font_id_e font_id; - ux_stack_slot_t* slot = &G_ux.stack[stack_slot]; -#if (BAGL_WIDTH==128 && BAGL_HEIGHT==64) - slot->element_arrays[0].element_array = ux_layout_paging_elements; - slot->element_arrays[0].element_array_count = ARRAYLEN(ux_layout_paging_elements); - slot->element_arrays_count = 1; +void ux_layout_paging_redisplay_common(unsigned int stack_slot, + const char *text, + button_push_callback_t button_callback, + bagl_element_callback_t prepro) +{ + bagl_font_id_e font_id; + ux_stack_slot_t *slot = &G_ux.stack[stack_slot]; +#if (BAGL_WIDTH == 128 && BAGL_HEIGHT == 64) + slot->element_arrays[0].element_array = ux_layout_paging_elements; + slot->element_arrays[0].element_array_count = ARRAYLEN(ux_layout_paging_elements); + slot->element_arrays_count = 1; #else - ux_layout_bb_init_common(stack_slot); -#endif // (BAGL_WIDTH==128 && BAGL_HEIGHT==64) - - // Use the correct font, to be able to compute correctly text width: - if (G_ux.layout_paging.format & PAGING_FORMAT_NB) { - font_id = BAGL_FONT_OPEN_SANS_EXTRABOLD_11px; - } else { - font_id = BAGL_FONT_OPEN_SANS_REGULAR_11px; - } - // request offsets and lengths of lines for the current page - ux_layout_paging_compute(text, - G_ux.layout_paging.current, - &G_ux.layout_paging, - font_id); - - slot->screen_before_element_display_callback = prepro; - slot->button_push_callback = button_callback; - ux_stack_display(stack_slot); + ux_layout_bb_init_common(stack_slot); +#endif // (BAGL_WIDTH==128 && BAGL_HEIGHT==64) + + // Use the correct font, to be able to compute correctly text width: + if (G_ux.layout_paging.format & PAGING_FORMAT_NB) { + font_id = BAGL_FONT_OPEN_SANS_EXTRABOLD_11px; + } + else { + font_id = BAGL_FONT_OPEN_SANS_REGULAR_11px; + } + // request offsets and lengths of lines for the current page + ux_layout_paging_compute(text, G_ux.layout_paging.current, &G_ux.layout_paging, font_id); + + slot->screen_before_element_display_callback = prepro; + slot->button_push_callback = button_callback; + ux_stack_display(stack_slot); } -STATIC_IF_NOT_INDEXED unsigned int ux_layout_paging_button_callback_by_addr(unsigned int button_mask, unsigned int button_mask_counter); +STATIC_IF_NOT_INDEXED unsigned int ux_layout_paging_button_callback_by_addr( + unsigned int button_mask, + unsigned int button_mask_counter); -void ux_layout_paging_redisplay_by_addr(unsigned int stack_slot) { - const char* text; - const void *params = ux_stack_get_current_step_params(); - if (NULL == params) { - return; - } +void ux_layout_paging_redisplay_by_addr(unsigned int stack_slot) +{ + const char *text; + const void *params = ux_stack_get_current_step_params(); + if (NULL == params) { + return; + } #if defined(HAVE_INDEXED_STRINGS) - text = get_ux_loc_string(((const ux_loc_layout_params_t*)params)->index+1); -#else //defined(HAVE_INDEXED_STRINGS) - text = ((const ux_layout_paging_params_t*)params)->text; -#endif //defined(HAVE_INDEXED_STRINGS) - ux_layout_paging_redisplay_common(stack_slot, text, ux_layout_paging_button_callback_by_addr, ux_layout_paging_prepro_by_addr); + text = get_ux_loc_string(((const ux_loc_layout_params_t *) params)->index + 1); +#else // defined(HAVE_INDEXED_STRINGS) + text = ((const ux_layout_paging_params_t *) params)->text; +#endif // defined(HAVE_INDEXED_STRINGS) + ux_layout_paging_redisplay_common(stack_slot, + text, + ux_layout_paging_button_callback_by_addr, + ux_layout_paging_prepro_by_addr); } -static void ux_layout_paging_next(ux_layout_paging_redisplay_t redisplay) { - if (G_ux.layout_paging.current == G_ux.layout_paging.count-1) { - ux_flow_next(); - } - else { - // display next page, count the number of char to fit in the next page - G_ux.layout_paging.current++; - redisplay(G_ux.stack_count-1); - } +static void ux_layout_paging_next(ux_layout_paging_redisplay_t redisplay) +{ + if (G_ux.layout_paging.current == G_ux.layout_paging.count - 1) { + ux_flow_next(); + } + else { + // display next page, count the number of char to fit in the next page + G_ux.layout_paging.current++; + redisplay(G_ux.stack_count - 1); + } } -static void ux_layout_paging_prev(ux_layout_paging_redisplay_t redisplay) { - if (G_ux.layout_paging.current == 0) { - ux_flow_prev(); - } - else { - // display previous page, count the number of char to fit in the previous page - G_ux.layout_paging.current--; - redisplay(G_ux.stack_count-1); - } +static void ux_layout_paging_prev(ux_layout_paging_redisplay_t redisplay) +{ + if (G_ux.layout_paging.current == 0) { + ux_flow_prev(); + } + else { + // display previous page, count the number of char to fit in the previous page + G_ux.layout_paging.current--; + redisplay(G_ux.stack_count - 1); + } } -STATIC_IF_NOT_INDEXED unsigned int ux_layout_paging_button_callback_common(unsigned int button_mask, unsigned int button_mask_counter, ux_layout_paging_redisplay_t redisplay) { - UNUSED(button_mask_counter); - switch(button_mask) { - case BUTTON_EVT_RELEASED|BUTTON_LEFT: - ux_layout_paging_prev(redisplay); - break; - case BUTTON_EVT_RELEASED|BUTTON_RIGHT: - ux_layout_paging_next(redisplay); - break; - case BUTTON_EVT_RELEASED|BUTTON_LEFT|BUTTON_RIGHT: - if (G_ux.layout_paging.count == 0 - || G_ux.layout_paging.count-1 == G_ux.layout_paging.current) { - ux_flow_validate(); - } - break; - } - return 0; +STATIC_IF_NOT_INDEXED unsigned int ux_layout_paging_button_callback_common( + unsigned int button_mask, + unsigned int button_mask_counter, + ux_layout_paging_redisplay_t redisplay) +{ + UNUSED(button_mask_counter); + switch (button_mask) { + case BUTTON_EVT_RELEASED | BUTTON_LEFT: + ux_layout_paging_prev(redisplay); + break; + case BUTTON_EVT_RELEASED | BUTTON_RIGHT: + ux_layout_paging_next(redisplay); + break; + case BUTTON_EVT_RELEASED | BUTTON_LEFT | BUTTON_RIGHT: + if (G_ux.layout_paging.count == 0 + || G_ux.layout_paging.count - 1 == G_ux.layout_paging.current) { + ux_flow_validate(); + } + break; + } + return 0; } -STATIC_IF_NOT_INDEXED unsigned int ux_layout_paging_button_callback_by_addr(unsigned int button_mask, unsigned int button_mask_counter) { - return ux_layout_paging_button_callback_common(button_mask, button_mask_counter, ux_layout_paging_redisplay_by_addr); +STATIC_IF_NOT_INDEXED unsigned int ux_layout_paging_button_callback_by_addr( + unsigned int button_mask, + unsigned int button_mask_counter) +{ + return ux_layout_paging_button_callback_common( + button_mask, button_mask_counter, ux_layout_paging_redisplay_by_addr); } -void ux_layout_paging_init_common(unsigned int stack_slot, const char* text, ux_layout_paging_redisplay_t redisplay) { - - bagl_font_id_e font_id; - - // At this very moment, we don't want to get rid of the format, but keep - // the one which has just been set (in case of direction backward or forward). - unsigned int backup_format = G_ux.layout_paging.format; - - // depending flow browsing direction, select the correct page to display - switch(ux_flow_direction()) { - case FLOW_DIRECTION_BACKWARD: - ux_layout_paging_reset(); - // ask the paging to start at the last page. - // This step must be performed after the 'ux_layout_paging_reset' call, - // thus we cannot mutualize the call with the one in the 'forward' case. - G_ux.layout_paging.current = -1UL; - break; - case FLOW_DIRECTION_FORWARD: - // open the first page - ux_layout_paging_reset(); - break; - case FLOW_DIRECTION_START: - // shall already be at the first page - break; - } - - G_ux.layout_paging.format = backup_format; - - // store params - ux_stack_init(stack_slot); - - // compute number of chars to display from the params complete string - if ((text == NULL) && (G_ux.externalText == NULL)) { - text = ""; // empty string to avoid disrupting the ux flow. - } - - // Use the correct font, to be able to compute correctly text width: - if (G_ux.layout_paging.format & PAGING_FORMAT_NB) { - font_id = BAGL_FONT_OPEN_SANS_EXTRABOLD_11px; - } else { - font_id = BAGL_FONT_OPEN_SANS_REGULAR_11px; - } - - // count total number of pages - G_ux.layout_paging.count = ux_layout_paging_compute(text, -1UL, &G_ux.layout_paging, font_id); // at least one page - - if (G_ux.layout_paging.count == 0) { - ux_layout_paging_reset(); - } - - // if (start != end) { - // ux_layout_paging_reset(); - // } - - // perform displaying the last page as requested (-1UL in prevstep hook does this) - if (G_ux.layout_paging.count && G_ux.layout_paging.current > G_ux.layout_paging.count-1UL) { - G_ux.layout_paging.current = G_ux.layout_paging.count-1; - } - - redisplay(stack_slot); +void ux_layout_paging_init_common(unsigned int stack_slot, + const char *text, + ux_layout_paging_redisplay_t redisplay) +{ + bagl_font_id_e font_id; + + // At this very moment, we don't want to get rid of the format, but keep + // the one which has just been set (in case of direction backward or forward). + unsigned int backup_format = G_ux.layout_paging.format; + + // depending flow browsing direction, select the correct page to display + switch (ux_flow_direction()) { + case FLOW_DIRECTION_BACKWARD: + ux_layout_paging_reset(); + // ask the paging to start at the last page. + // This step must be performed after the 'ux_layout_paging_reset' call, + // thus we cannot mutualize the call with the one in the 'forward' case. + G_ux.layout_paging.current = -1UL; + break; + case FLOW_DIRECTION_FORWARD: + // open the first page + ux_layout_paging_reset(); + break; + case FLOW_DIRECTION_START: + // shall already be at the first page + break; + } + + G_ux.layout_paging.format = backup_format; + + // store params + ux_stack_init(stack_slot); + + // compute number of chars to display from the params complete string + if ((text == NULL) && (G_ux.externalText == NULL)) { + text = ""; // empty string to avoid disrupting the ux flow. + } + + // Use the correct font, to be able to compute correctly text width: + if (G_ux.layout_paging.format & PAGING_FORMAT_NB) { + font_id = BAGL_FONT_OPEN_SANS_EXTRABOLD_11px; + } + else { + font_id = BAGL_FONT_OPEN_SANS_REGULAR_11px; + } + + // count total number of pages + G_ux.layout_paging.count + = ux_layout_paging_compute(text, -1UL, &G_ux.layout_paging, font_id); // at least one page + + if (G_ux.layout_paging.count == 0) { + ux_layout_paging_reset(); + } + + // if (start != end) { + // ux_layout_paging_reset(); + // } + + // perform displaying the last page as requested (-1UL in prevstep hook does this) + if (G_ux.layout_paging.count && G_ux.layout_paging.current > G_ux.layout_paging.count - 1UL) { + G_ux.layout_paging.current = G_ux.layout_paging.count - 1; + } + + redisplay(stack_slot); } -void ux_layout_paging_init(unsigned int stack_slot) { - const ux_layout_paging_params_t* params = (const ux_layout_paging_params_t*)ux_stack_get_step_params(stack_slot); - ux_layout_paging_init_common(stack_slot, params->text, ux_layout_paging_redisplay_by_addr); +void ux_layout_paging_init(unsigned int stack_slot) +{ + const ux_layout_paging_params_t *params + = (const ux_layout_paging_params_t *) ux_stack_get_step_params(stack_slot); + ux_layout_paging_init_common(stack_slot, params->text, ux_layout_paging_redisplay_by_addr); } -void ux_layout_xx_paging_init(unsigned int stack_slot, unsigned int format) { - G_ux.layout_paging.format = format; - ux_layout_paging_init(stack_slot); +void ux_layout_xx_paging_init(unsigned int stack_slot, unsigned int format) +{ + G_ux.layout_paging.format = format; + ux_layout_paging_init(stack_slot); } -void ux_layout_nn_paging_init(unsigned int stack_slot) { - ux_layout_xx_paging_init(stack_slot, PAGING_FORMAT_NN); +void ux_layout_nn_paging_init(unsigned int stack_slot) +{ + ux_layout_xx_paging_init(stack_slot, PAGING_FORMAT_NN); } -void ux_layout_nb_paging_init(unsigned int stack_slot) { - ux_layout_xx_paging_init(stack_slot, PAGING_FORMAT_NB); +void ux_layout_nb_paging_init(unsigned int stack_slot) +{ + ux_layout_xx_paging_init(stack_slot, PAGING_FORMAT_NB); } -void ux_layout_bn_paging_init(unsigned int stack_slot) { - ux_layout_xx_paging_init(stack_slot, PAGING_FORMAT_BN); +void ux_layout_bn_paging_init(unsigned int stack_slot) +{ + ux_layout_xx_paging_init(stack_slot, PAGING_FORMAT_BN); } -void ux_layout_bb_paging_init(unsigned int stack_slot) { - ux_layout_xx_paging_init(stack_slot, PAGING_FORMAT_BB); +void ux_layout_bb_paging_init(unsigned int stack_slot) +{ + ux_layout_xx_paging_init(stack_slot, PAGING_FORMAT_BB); } -// function callable externally which reset the paging (to be called before init when willing to redisplay the first page) -void ux_layout_paging_reset(void) { - memset(&G_ux.layout_paging, 0, sizeof(G_ux.layout_paging)); +// function callable externally which reset the paging (to be called before init when willing to +// redisplay the first page) +void ux_layout_paging_reset(void) +{ + memset(&G_ux.layout_paging, 0, sizeof(G_ux.layout_paging)); } -#endif // HAVE_BAGL +#endif // HAVE_BAGL -#endif // HAVE_UX_FLOW +#endif // HAVE_UX_FLOW diff --git a/lib_ux/src/ux_layout_paging_compute.c b/lib_ux/src/ux_layout_paging_compute.c index 47d656a53..b12065c81 100644 --- a/lib_ux/src/ux_layout_paging_compute.c +++ b/lib_ux/src/ux_layout_paging_compute.c @@ -15,137 +15,120 @@ // nano S characters, in the two possible fonts: // - BAGL_FONT_OPEN_SANS_EXTRABOLD_11px, // - BAGL_FONT_OPEN_SANS_REGULAR_11px. -#define NANOS_FIRST_CHAR 0x20 -#define NANOS_LAST_CHAR 0x7F +#define NANOS_FIRST_CHAR 0x20 +#define NANOS_LAST_CHAR 0x7F // OPEN_SANS_REGULAR_11PX << 4 | OPEN_SANS_EXTRABOLD_11PX // Check with files (in the bagl_font_character_t array): // - common/bagl/src/bagl_font_open_sans_extrabold_11px.inc // - common/bagl/src/bagl_font_open_sans_regular_11px.inc const char nanos_characters_width[96] = { - 3 << 4 | 3, /* code 0020 */ - 3 << 4 | 3, /* code 0021 */ - 4 << 4 | 6, /* code 0022 */ - 7 << 4 | 7, /* code 0023 */ - 6 << 4 | 6, /* code 0024 */ - 9 << 4 | 10, /* code 0025 */ - 8 << 4 | 9, /* code 0026 */ - 2 << 4 | 3, /* code 0027 */ - 3 << 4 | 4, /* code 0028 */ - 3 << 4 | 4, /* code 0029 */ - 6 << 4 | 6, /* code 002A */ - 6 << 4 | 6, /* code 002B */ - 3 << 4 | 3, /* code 002C */ - 4 << 4 | 4, /* code 002D */ - 3 << 4 | 3, /* code 002E */ - 4 << 4 | 5, /* code 002F */ - 6 << 4 | 8, /* code 0030 */ - 6 << 4 | 6, /* code 0031 */ - 6 << 4 | 7, /* code 0032 */ - 6 << 4 | 7, /* code 0033 */ - 8 << 4 | 8, /* code 0034 */ - 6 << 4 | 6, /* code 0035 */ - 6 << 4 | 8, /* code 0036 */ - 6 << 4 | 7, /* code 0037 */ - 6 << 4 | 8, /* code 0038 */ - 6 << 4 | 8, /* code 0039 */ - 3 << 4 | 3, /* code 003A */ - 3 << 4 | 3, /* code 003B */ - 6 << 4 | 5, /* code 003C */ - 6 << 4 | 6, /* code 003D */ - 6 << 4 | 5, /* code 003E */ - 5 << 4 | 6, /* code 003F */ - 10 << 4 | 10, /* code 0040 */ - 7 << 4 | 8, /* code 0041 */ - 7 << 4 | 7, /* code 0042 */ - 7 << 4 | 7, /* code 0043 */ - 8 << 4 | 8, /* code 0044 */ - 6 << 4 | 6, /* code 0045 */ - 6 << 4 | 6, /* code 0046 */ - 8 << 4 | 8, /* code 0047 */ - 8 << 4 | 8, /* code 0048 */ - 3 << 4 | 4, /* code 0049 */ - 4 << 4 | 5, /* code 004A */ - 7 << 4 | 8, /* code 004B */ - 6 << 4 | 6, /* code 004C */ - 10 << 4 | 11, /* code 004D */ - 8 << 4 | 9, /* code 004E */ - 9 << 4 | 9, /* code 004F */ - 7 << 4 | 7, /* code 0050 */ - 9 << 4 | 9, /* code 0051 */ - 7 << 4 | 8, /* code 0052 */ - 6 << 4 | 6, /* code 0053 */ - 7 << 4 | 6, /* code 0054 */ - 8 << 4 | 8, /* code 0055 */ - 7 << 4 | 6, /* code 0056 */ - 10 << 4 | 11, /* code 0057 */ - 6 << 4 | 8, /* code 0058 */ - 6 << 4 | 7, /* code 0059 */ - 6 << 4 | 7, /* code 005A */ - 4 << 4 | 5, /* code 005B */ - 4 << 4 | 5, /* code 005C */ - 4 << 4 | 5, /* code 005D */ - 6 << 4 | 7, /* code 005E */ - 5 << 4 | 6, /* code 005F */ - 6 << 4 | 7, /* code 0060 */ - 6 << 4 | 7, /* code 0061 */ - 7 << 4 | 7, /* code 0062 */ - 5 << 4 | 6, /* code 0063 */ - 7 << 4 | 7, /* code 0064 */ - 6 << 4 | 7, /* code 0065 */ - 5 << 4 | 6, /* code 0066 */ - 6 << 4 | 7, /* code 0067 */ - 7 << 4 | 7, /* code 0068 */ - 3 << 4 | 4, /* code 0069 */ - 4 << 4 | 5, /* code 006A */ - 6 << 4 | 7, /* code 006B */ - 3 << 4 | 4, /* code 006C */ - 10 << 4 | 10, /* code 006D */ - 7 << 4 | 7, /* code 006E */ - 7 << 4 | 7, /* code 006F */ - 7 << 4 | 7, /* code 0070 */ - 7 << 4 | 7, /* code 0071 */ - 4 << 4 | 5, /* code 0072 */ - 5 << 4 | 6, /* code 0073 */ - 4 << 4 | 5, /* code 0074 */ - 7 << 4 | 7, /* code 0075 */ - 6 << 4 | 7, /* code 0076 */ - 9 << 4 | 10, /* code 0077 */ - 6 << 4 | 7, /* code 0078 */ - 6 << 4 | 7, /* code 0079 */ - 5 << 4 | 6, /* code 007A */ - 4 << 4 | 5, /* code 007B */ - 6 << 4 | 6, /* code 007C */ - 4 << 4 | 5, /* code 007D */ - 6 << 4 | 6, /* code 007E */ - 7 << 4 | 6, /* code 007F */ + 3 << 4 | 3, /* code 0020 */ + 3 << 4 | 3, /* code 0021 */ + 4 << 4 | 6, /* code 0022 */ + 7 << 4 | 7, /* code 0023 */ + 6 << 4 | 6, /* code 0024 */ + 9 << 4 | 10, /* code 0025 */ + 8 << 4 | 9, /* code 0026 */ + 2 << 4 | 3, /* code 0027 */ + 3 << 4 | 4, /* code 0028 */ + 3 << 4 | 4, /* code 0029 */ + 6 << 4 | 6, /* code 002A */ + 6 << 4 | 6, /* code 002B */ + 3 << 4 | 3, /* code 002C */ + 4 << 4 | 4, /* code 002D */ + 3 << 4 | 3, /* code 002E */ + 4 << 4 | 5, /* code 002F */ + 6 << 4 | 8, /* code 0030 */ + 6 << 4 | 6, /* code 0031 */ + 6 << 4 | 7, /* code 0032 */ + 6 << 4 | 7, /* code 0033 */ + 8 << 4 | 8, /* code 0034 */ + 6 << 4 | 6, /* code 0035 */ + 6 << 4 | 8, /* code 0036 */ + 6 << 4 | 7, /* code 0037 */ + 6 << 4 | 8, /* code 0038 */ + 6 << 4 | 8, /* code 0039 */ + 3 << 4 | 3, /* code 003A */ + 3 << 4 | 3, /* code 003B */ + 6 << 4 | 5, /* code 003C */ + 6 << 4 | 6, /* code 003D */ + 6 << 4 | 5, /* code 003E */ + 5 << 4 | 6, /* code 003F */ + 10 << 4 | 10, /* code 0040 */ + 7 << 4 | 8, /* code 0041 */ + 7 << 4 | 7, /* code 0042 */ + 7 << 4 | 7, /* code 0043 */ + 8 << 4 | 8, /* code 0044 */ + 6 << 4 | 6, /* code 0045 */ + 6 << 4 | 6, /* code 0046 */ + 8 << 4 | 8, /* code 0047 */ + 8 << 4 | 8, /* code 0048 */ + 3 << 4 | 4, /* code 0049 */ + 4 << 4 | 5, /* code 004A */ + 7 << 4 | 8, /* code 004B */ + 6 << 4 | 6, /* code 004C */ + 10 << 4 | 11, /* code 004D */ + 8 << 4 | 9, /* code 004E */ + 9 << 4 | 9, /* code 004F */ + 7 << 4 | 7, /* code 0050 */ + 9 << 4 | 9, /* code 0051 */ + 7 << 4 | 8, /* code 0052 */ + 6 << 4 | 6, /* code 0053 */ + 7 << 4 | 6, /* code 0054 */ + 8 << 4 | 8, /* code 0055 */ + 7 << 4 | 6, /* code 0056 */ + 10 << 4 | 11, /* code 0057 */ + 6 << 4 | 8, /* code 0058 */ + 6 << 4 | 7, /* code 0059 */ + 6 << 4 | 7, /* code 005A */ + 4 << 4 | 5, /* code 005B */ + 4 << 4 | 5, /* code 005C */ + 4 << 4 | 5, /* code 005D */ + 6 << 4 | 7, /* code 005E */ + 5 << 4 | 6, /* code 005F */ + 6 << 4 | 7, /* code 0060 */ + 6 << 4 | 7, /* code 0061 */ + 7 << 4 | 7, /* code 0062 */ + 5 << 4 | 6, /* code 0063 */ + 7 << 4 | 7, /* code 0064 */ + 6 << 4 | 7, /* code 0065 */ + 5 << 4 | 6, /* code 0066 */ + 6 << 4 | 7, /* code 0067 */ + 7 << 4 | 7, /* code 0068 */ + 3 << 4 | 4, /* code 0069 */ + 4 << 4 | 5, /* code 006A */ + 6 << 4 | 7, /* code 006B */ + 3 << 4 | 4, /* code 006C */ + 10 << 4 | 10, /* code 006D */ + 7 << 4 | 7, /* code 006E */ + 7 << 4 | 7, /* code 006F */ + 7 << 4 | 7, /* code 0070 */ + 7 << 4 | 7, /* code 0071 */ + 4 << 4 | 5, /* code 0072 */ + 5 << 4 | 6, /* code 0073 */ + 4 << 4 | 5, /* code 0074 */ + 7 << 4 | 7, /* code 0075 */ + 6 << 4 | 7, /* code 0076 */ + 9 << 4 | 10, /* code 0077 */ + 6 << 4 | 7, /* code 0078 */ + 6 << 4 | 7, /* code 0079 */ + 5 << 4 | 6, /* code 007A */ + 4 << 4 | 5, /* code 007B */ + 6 << 4 | 6, /* code 007C */ + 4 << 4 | 5, /* code 007D */ + 6 << 4 | 6, /* code 007E */ + 7 << 4 | 6, /* code 007F */ }; #if defined(HAVE_UNICODE_SUPPORT) // That first array will helps find the index of the unicode char: const unsigned int nanos_unicode_index[] = { - 0x0000A1, - 0x0000BF, - 0x0000C9, - 0x0000E0, - 0x0000E1, - 0x0000E2, - 0x0000E7, - 0x0000E8, - 0x0000E9, - 0x0000EA, - 0x0000EB, - 0x0000ED, - 0x0000EE, - 0x0000EF, - 0x0000F1, - 0x0000F3, - 0x0000F4, - 0x0000F9, - 0x0000FA, - 0x0000FB - // No need to enter FFFD, because it will be the one we'll use by default - //0x00FFFD + 0x0000A1, 0x0000BF, 0x0000C9, 0x0000E0, 0x0000E1, 0x0000E2, 0x0000E7, + 0x0000E8, 0x0000E9, 0x0000EA, 0x0000EB, 0x0000ED, 0x0000EE, 0x0000EF, + 0x0000F1, 0x0000F3, 0x0000F4, 0x0000F9, 0x0000FA, 0x0000FB + // No need to enter FFFD, because it will be the one we'll use by default + // 0x00FFFD }; // OPEN_SANS_REGULAR_11PX_UNICODE << 4 | OPEN_SANS_EXTRABOLD_11PX_UNICODE @@ -153,309 +136,326 @@ const unsigned int nanos_unicode_index[] = { // - common/bagl/src/bagl_font_open_sans_extrabold_11px_unicode.inc // - common/bagl/src/bagl_font_open_sans_regular_11px_unicode.inc const unsigned char nanos_unicode_width[] = { - 3 << 4 | 3, //unicode 0x0000A1 - 5 << 4 | 6, //unicode 0x0000BF - 6 << 4 | 6, //unicode 0x0000C9 - 6 << 4 | 7, //unicode 0x0000E0 - 6 << 4 | 7, //unicode 0x0000E1 - 6 << 4 | 7, //unicode 0x0000E2 - 5 << 4 | 6, //unicode 0x0000E7 - 6 << 4 | 7, //unicode 0x0000E8 - 6 << 4 | 7, //unicode 0x0000E9 - 6 << 4 | 7, //unicode 0x0000EA - 6 << 4 | 7, //unicode 0x0000EB - 4 << 4 | 5, //unicode 0x0000ED - 5 << 4 | 6, //unicode 0x0000EE - 4 << 4 | 6, //unicode 0x0000EF - 7 << 4 | 7, //unicode 0x0000F1 - 7 << 4 | 7, //unicode 0x0000F3 - 7 << 4 | 7, //unicode 0x0000F4 - 7 << 4 | 7, //unicode 0x0000F9 - 7 << 4 | 7, //unicode 0x0000FA - 7 << 4 | 7 //unicode 0x0000FB - // No need to enter FFFD, because it will be the one we'll use by default - //11 << 4 |11 //unicode 0x00FFFD + 3 << 4 | 3, // unicode 0x0000A1 + 5 << 4 | 6, // unicode 0x0000BF + 6 << 4 | 6, // unicode 0x0000C9 + 6 << 4 | 7, // unicode 0x0000E0 + 6 << 4 | 7, // unicode 0x0000E1 + 6 << 4 | 7, // unicode 0x0000E2 + 5 << 4 | 6, // unicode 0x0000E7 + 6 << 4 | 7, // unicode 0x0000E8 + 6 << 4 | 7, // unicode 0x0000E9 + 6 << 4 | 7, // unicode 0x0000EA + 6 << 4 | 7, // unicode 0x0000EB + 4 << 4 | 5, // unicode 0x0000ED + 5 << 4 | 6, // unicode 0x0000EE + 4 << 4 | 6, // unicode 0x0000EF + 7 << 4 | 7, // unicode 0x0000F1 + 7 << 4 | 7, // unicode 0x0000F3 + 7 << 4 | 7, // unicode 0x0000F4 + 7 << 4 | 7, // unicode 0x0000F9 + 7 << 4 | 7, // unicode 0x0000FA + 7 << 4 | 7 // unicode 0x0000FB + // No need to enter FFFD, because it will be the one we'll use by default + // 11 << 4 |11 //unicode 0x00FFFD }; -#define DEFAULT_NANOS_UNICODE_WIDTH ((unsigned char)(11 << 4 |11)) // For unicode FFFD - -#define NB_NANOS_UNICODE_CHARS (sizeof(nanos_unicode_width)/sizeof(nanos_unicode_width[0])) -#endif //defined(HAVE_UNICODE_SUPPORT) - -// This function is used to retrieve the length of a string (expressed in bytes) delimited with a boundary width (expressed in pixels). -uint8_t se_get_cropped_length(const char* text, uint8_t text_length, uint32_t width_limit_in_pixels, uint8_t text_format) { - char current_char; - uint8_t length; - uint32_t current_width_in_pixels = 0; - - for (length = 0; length < text_length; length++) { - current_char = text[length]; - - if ((text_format & PAGING_FORMAT_NB) == PAGING_FORMAT_NB) { - // Bold. - current_width_in_pixels += nanos_characters_width[current_char - NANOS_FIRST_CHAR] & 0x0F; - } - else { - // Regular. - current_width_in_pixels += (nanos_characters_width[current_char - NANOS_FIRST_CHAR] >> 0x04) & 0x0F; - } +#define DEFAULT_NANOS_UNICODE_WIDTH ((unsigned char) (11 << 4 | 11)) // For unicode FFFD + +#define NB_NANOS_UNICODE_CHARS (sizeof(nanos_unicode_width) / sizeof(nanos_unicode_width[0])) +#endif // defined(HAVE_UNICODE_SUPPORT) + +// This function is used to retrieve the length of a string (expressed in bytes) delimited with a +// boundary width (expressed in pixels). +uint8_t se_get_cropped_length(const char *text, + uint8_t text_length, + uint32_t width_limit_in_pixels, + uint8_t text_format) +{ + char current_char; + uint8_t length; + uint32_t current_width_in_pixels = 0; + + for (length = 0; length < text_length; length++) { + current_char = text[length]; + + if ((text_format & PAGING_FORMAT_NB) == PAGING_FORMAT_NB) { + // Bold. + current_width_in_pixels + += nanos_characters_width[current_char - NANOS_FIRST_CHAR] & 0x0F; + } + else { + // Regular. + current_width_in_pixels + += (nanos_characters_width[current_char - NANOS_FIRST_CHAR] >> 0x04) & 0x0F; + } - // We stop the processing when we reached the limit. - if (current_width_in_pixels > width_limit_in_pixels) { - break; + // We stop the processing when we reached the limit. + if (current_width_in_pixels > width_limit_in_pixels) { + break; + } } - } - return length; + return length; } // This function is used to retrieve the width of a line of text. -STATIC_IF_NOT_INDEXED unsigned int se_compute_line_width_light(const char* text, uint8_t text_length, uint8_t text_format) { - unsigned char ch; - unsigned int line_width = 0; -#if defined(HAVE_INDEXED_STRINGS) - unsigned int width = 0; - unsigned char bold_toggle = 0; - - // Bold state at the beginning of the line: - if ((text_format & PAGING_FORMAT_NB) == PAGING_FORMAT_NB) { - bold_toggle = 1; - } -#endif //defined(HAVE_INDEXED_STRINGS) - - // We parse the characters of the input text on all the input length. - while (text_length--) { - ch = *(const unsigned char *)text; +STATIC_IF_NOT_INDEXED unsigned int se_compute_line_width_light(const char *text, + uint8_t text_length, + uint8_t text_format) +{ + unsigned char ch; + unsigned int line_width = 0; #if defined(HAVE_INDEXED_STRINGS) - ++text; - width = 0; -#endif //defined(HAVE_INDEXED_STRINGS) + unsigned int width = 0; + unsigned char bold_toggle = 0; -#if defined(HAVE_UNICODE_SUPPORT) - unsigned int unicode; - - // Handle UTF-8 decoding (RFC3629): (https://www.ietf.org/rfc/rfc3629.txt - // Char. number range | UTF-8 octet sequence - // (hexadecimal) | (binary) - // --------------------+--------------------------------------------- - // 0000 0000-0000 007F | 0xxxxxxx - // 0000 0080-0000 07FF | 110xxxxx 10xxxxxx - // 0000 0800-0000 FFFF | 1110xxxx 10xxxxxx 10xxxxxx - // 0001 0000-0010 FFFF | 11110xxx 10xxxxxx 10xxxxxx 10xxxxxx - - // 4 bytes UTF-8, Unicode 0x1000 to 0x1FFFF - if (ch >= 0xF0 && text_length >= 3) { - unicode = (ch & 0x07) << 18; - unicode |= (*((const unsigned char*)text+0) & 0x3F) << 12; - unicode |= (*((const unsigned char*)text+1) & 0x3F) << 6; - unicode |= (*((const unsigned char*)text+2) & 0x3F); - text += 3; - text_length -= 3; - - // 3 bytes, from 0x800 to 0xFFFF - } else if (ch >= 0xE0 && text_length >= 2) { - unicode = (ch & 0x0F) << 12; - unicode |= (*((const unsigned char*)text+0) & 0x3F) << 6; - unicode |= (*((const unsigned char*)text+1) & 0x3F); - text += 2; - text_length -= 2; - - // 2 bytes UTF-8, Unicode 0x80 to 0x7FF - // (0xC0 & 0xC1 are unused and can be used to store something else) - } else if (ch >= 0xC2 && text_length >= 1) { - unicode = (ch & 0x1F) << 6; - unicode |= (*((const unsigned char*)text+0) & 0x3F); - ++text; - text_length -= 1; - - } else { - unicode = 0; + // Bold state at the beginning of the line: + if ((text_format & PAGING_FORMAT_NB) == PAGING_FORMAT_NB) { + bold_toggle = 1; } -#endif //defined(HAVE_UNICODE_SUPPORT) +#endif // defined(HAVE_INDEXED_STRINGS) - if (ch < NANOS_FIRST_CHAR || ch > NANOS_LAST_CHAR) { + // We parse the characters of the input text on all the input length. + while (text_length--) { + ch = *(const unsigned char *) text; #if defined(HAVE_INDEXED_STRINGS) - // Only proceed the first line width, not the whole paragraph - switch(ch) { - case '\n': - case '\f': - return line_width; - case '\b': // Bold toggle: turn Bold On/Off - bold_toggle ^= 1; - continue; - case '\e': // Escape character => ignore it and the extra byte. - if (text_length >= 1) { // Take care of \e without additional byte! + ++text; + width = 0; +#endif // defined(HAVE_INDEXED_STRINGS) + +#if defined(HAVE_UNICODE_SUPPORT) + unsigned int unicode; + + // Handle UTF-8 decoding (RFC3629): (https://www.ietf.org/rfc/rfc3629.txt + // Char. number range | UTF-8 octet sequence + // (hexadecimal) | (binary) + // --------------------+--------------------------------------------- + // 0000 0000-0000 007F | 0xxxxxxx + // 0000 0080-0000 07FF | 110xxxxx 10xxxxxx + // 0000 0800-0000 FFFF | 1110xxxx 10xxxxxx 10xxxxxx + // 0001 0000-0010 FFFF | 11110xxx 10xxxxxx 10xxxxxx 10xxxxxx + + // 4 bytes UTF-8, Unicode 0x1000 to 0x1FFFF + if (ch >= 0xF0 && text_length >= 3) { + unicode = (ch & 0x07) << 18; + unicode |= (*((const unsigned char *) text + 0) & 0x3F) << 12; + unicode |= (*((const unsigned char *) text + 1) & 0x3F) << 6; + unicode |= (*((const unsigned char *) text + 2) & 0x3F); + text += 3; + text_length -= 3; + + // 3 bytes, from 0x800 to 0xFFFF + } + else if (ch >= 0xE0 && text_length >= 2) { + unicode = (ch & 0x0F) << 12; + unicode |= (*((const unsigned char *) text + 0) & 0x3F) << 6; + unicode |= (*((const unsigned char *) text + 1) & 0x3F); + text += 2; + text_length -= 2; + + // 2 bytes UTF-8, Unicode 0x80 to 0x7FF + // (0xC0 & 0xC1 are unused and can be used to store something else) + } + else if (ch >= 0xC2 && text_length >= 1) { + unicode = (ch & 0x1F) << 6; + unicode |= (*((const unsigned char *) text + 0) & 0x3F); ++text; text_length -= 1; - } - continue; - } -#else //defined(HAVE_INDEXED_STRINGS) - if (ch == '\n' || ch == '\r') { - break; - } -#endif //defined(HAVE_INDEXED_STRINGS) + } + else { + unicode = 0; + } +#endif // defined(HAVE_UNICODE_SUPPORT) + + if (ch < NANOS_FIRST_CHAR || ch > NANOS_LAST_CHAR) { +#if defined(HAVE_INDEXED_STRINGS) + // Only proceed the first line width, not the whole paragraph + switch (ch) { + case '\n': + case '\f': + return line_width; + case '\b': // Bold toggle: turn Bold On/Off + bold_toggle ^= 1; + continue; + case '\e': // Escape character => ignore it and the extra byte. + if (text_length >= 1) { // Take care of \e without additional byte! + ++text; + text_length -= 1; + } + continue; + } +#else // defined(HAVE_INDEXED_STRINGS) + if (ch == '\n' || ch == '\r') { + break; + } +#endif // defined(HAVE_INDEXED_STRINGS) #if defined(HAVE_UNICODE_SUPPORT) - if (unicode) { - unsigned int i; - // Find the index of the unicode character we are dealing with. - // For the moment, let just parse the full array, but at the end let - // use binary search as data are sorted by unicode value ! - for (i=0; i < NB_NANOS_UNICODE_CHARS; i++) { - if (nanos_unicode_index[i] == unicode) - break; - } - // Did we find a corresponding unicode entry? - if (i < NB_NANOS_UNICODE_CHARS) { - width = nanos_unicode_width[i]; - } else { - // No, use FFFD character width: - width = DEFAULT_NANOS_UNICODE_WIDTH; + if (unicode) { + unsigned int i; + // Find the index of the unicode character we are dealing with. + // For the moment, let just parse the full array, but at the end let + // use binary search as data are sorted by unicode value ! + for (i = 0; i < NB_NANOS_UNICODE_CHARS; i++) { + if (nanos_unicode_index[i] == unicode) { + break; + } + } + // Did we find a corresponding unicode entry? + if (i < NB_NANOS_UNICODE_CHARS) { + width = nanos_unicode_width[i]; + } + else { + // No, use FFFD character width: + width = DEFAULT_NANOS_UNICODE_WIDTH; + } + } +#endif // defined(HAVE_UNICODE_SUPPORT) } - } -#endif //defined(HAVE_UNICODE_SUPPORT) - } - else { + else { #if defined(HAVE_INDEXED_STRINGS) - ch -= NANOS_FIRST_CHAR; - width = nanos_characters_width[ch]; // 4 MSB = regular, 4 LSB = extrabold -#else //defined(HAVE_INDEXED_STRINGS) - // We retrieve the character width, and the paging format indicates whether we are - // processing bold characters or not. - if ((text_format & PAGING_FORMAT_NB) == PAGING_FORMAT_NB) { - // Bold. - line_width += nanos_characters_width[ch - NANOS_FIRST_CHAR] & 0x0F; - } - else { - // Regular. - line_width += (nanos_characters_width[ch - NANOS_FIRST_CHAR] >> 0x04) & 0x0F; - } -#endif //defined(HAVE_INDEXED_STRINGS) - } + ch -= NANOS_FIRST_CHAR; + width = nanos_characters_width[ch]; // 4 MSB = regular, 4 LSB = extrabold +#else // defined(HAVE_INDEXED_STRINGS) + // We retrieve the character width, and the paging format indicates whether we are + // processing bold characters or not. + if ((text_format & PAGING_FORMAT_NB) == PAGING_FORMAT_NB) { + // Bold. + line_width += nanos_characters_width[ch - NANOS_FIRST_CHAR] & 0x0F; + } + else { + // Regular. + line_width += (nanos_characters_width[ch - NANOS_FIRST_CHAR] >> 0x04) & 0x0F; + } +#endif // defined(HAVE_INDEXED_STRINGS) + } #if defined(HAVE_INDEXED_STRINGS) - if (width) { - if (!bold_toggle) { - width >>= 4; // 4 LSB = regular, now - } - width &= 0x0F; // Keep only the 4 LSB - line_width += width; + if (width) { + if (!bold_toggle) { + width >>= 4; // 4 LSB = regular, now + } + width &= 0x0F; // Keep only the 4 LSB + line_width += width; + } +#else // defined(HAVE_INDEXED_STRINGS) + text++; +#endif // defined(HAVE_INDEXED_STRINGS) } -#else //defined(HAVE_INDEXED_STRINGS) - text++; -#endif //defined(HAVE_INDEXED_STRINGS) - } - return line_width; + return line_width; } -#endif // !HAVE_SE_SCREEN +#endif // !HAVE_SE_SCREEN -static bool is_word_delim(unsigned char c) { - // return !((c >= 'a' && c <= 'z') - // || (c >= 'A' && c <= 'Z') - // || (c >= '0' && c <= '9')); - return c == ' ' || c == '\n' || c == '-' || c == '_'; +static bool is_word_delim(unsigned char c) +{ + // return !((c >= 'a' && c <= 'z') + // || (c >= 'A' && c <= 'Z') + // || (c >= '0' && c <= '9')); + return c == ' ' || c == '\n' || c == '-' || c == '_'; } // return the number of pages to be displayed when current page to show is -1 -unsigned int ux_layout_paging_compute(const char* text_to_split, - unsigned int page_to_display, - ux_layout_paging_state_t* paging_state, - bagl_font_id_e font - ) { +unsigned int ux_layout_paging_compute(const char *text_to_split, + unsigned int page_to_display, + ux_layout_paging_state_t *paging_state, + bagl_font_id_e font) +{ #ifndef HAVE_FONTS - UNUSED(font); + UNUSED(font); #endif - // reset length and offset of lines - memset(paging_state->offsets, 0, sizeof(paging_state->offsets)); - memset(paging_state->lengths, 0, sizeof(paging_state->lengths)); - - // a page has been asked, but no page exists - if (page_to_display >= paging_state->count && page_to_display != (unsigned int)-1) { - return 0; - } - - // compute offset/length of text of each line for the current page - unsigned int page = 0; - unsigned int line = 0; - const char* start = (text_to_split ? STRPIC(text_to_split) : G_ux.externalText); - const char* start2 = start; - const char* end = start + strlen(start); - while (start < end) { - unsigned int len = 0; - unsigned int linew = 0; - const char* last_word_delim = start; - // not reached end of content - while (start + len < end - // line is not full - && linew <= PIXEL_PER_LINE - // avoid display buffer overflow for each line - // && len < sizeof(G_ux.string_buffer)-1 - ) { - // compute new line length -#ifdef HAVE_FONTS - linew = bagl_compute_line_width(font, 0, start, len+1, BAGL_ENCODING_DEFAULT); -#else // HAVE_FONTS - linew = se_compute_line_width_light(start, len + 1, G_ux.layout_paging.format); -#endif //HAVE_FONTS - //if (start[len] ) - if (linew > PIXEL_PER_LINE) { - // we got a full line - break; - } - unsigned char c = start[len]; - if (is_word_delim(c)) { - last_word_delim = &start[len]; - } - len++; - // new line, don't go further - if (c == '\n') { - break; - } - } + // reset length and offset of lines + memset(paging_state->offsets, 0, sizeof(paging_state->offsets)); + memset(paging_state->lengths, 0, sizeof(paging_state->lengths)); - // if not splitting line onto a word delimiter, then cut at the previous word_delim, adjust len accordingly (and a wor delim has been found already) - if (start + len < end && last_word_delim != start && len) { - // if line split within a word - if ((!is_word_delim(start[len-1]) && !is_word_delim(start[len]))) { - len = last_word_delim - start; - } + // a page has been asked, but no page exists + if (page_to_display >= paging_state->count && page_to_display != (unsigned int) -1) { + return 0; } - // fill up the paging structure - if (page_to_display != (unsigned int)-1 && page_to_display == page && page_to_display < paging_state->count) { - paging_state->offsets[line] = start - start2; - paging_state->lengths[line] = len; + // compute offset/length of text of each line for the current page + unsigned int page = 0; + unsigned int line = 0; + const char *start = (text_to_split ? STRPIC(text_to_split) : G_ux.externalText); + const char *start2 = start; + const char *end = start + strlen(start); + while (start < end) { + unsigned int len = 0; + unsigned int linew = 0; + const char *last_word_delim = start; + // not reached end of content + while (start + len < end + // line is not full + && linew <= PIXEL_PER_LINE + // avoid display buffer overflow for each line + // && len < sizeof(G_ux.string_buffer)-1 + ) { + // compute new line length +#ifdef HAVE_FONTS + linew = bagl_compute_line_width(font, 0, start, len + 1, BAGL_ENCODING_DEFAULT); +#else // HAVE_FONTS + linew = se_compute_line_width_light(start, len + 1, G_ux.layout_paging.format); +#endif // HAVE_FONTS + // if (start[len] ) + if (linew > PIXEL_PER_LINE) { + // we got a full line + break; + } + unsigned char c = start[len]; + if (is_word_delim(c)) { + last_word_delim = &start[len]; + } + len++; + // new line, don't go further + if (c == '\n') { + break; + } + } + + // if not splitting line onto a word delimiter, then cut at the previous word_delim, adjust + // len accordingly (and a wor delim has been found already) + if (start + len < end && last_word_delim != start && len) { + // if line split within a word + if ((!is_word_delim(start[len - 1]) && !is_word_delim(start[len]))) { + len = last_word_delim - start; + } + } - // won't compute all pages, we reached the one to display + // fill up the paging structure + if (page_to_display != (unsigned int) -1 && page_to_display == page + && page_to_display < paging_state->count) { + paging_state->offsets[line] = start - start2; + paging_state->lengths[line] = len; + + // won't compute all pages, we reached the one to display #if UX_LAYOUT_PAGING_LINE_COUNT > 1 - if (line >= UX_LAYOUT_PAGING_LINE_COUNT-1) -#endif // UX_LAYOUT_PAGING_LINE_COUNT - { - // a page has been computed - return 1; - } - } + if (line >= UX_LAYOUT_PAGING_LINE_COUNT - 1) +#endif // UX_LAYOUT_PAGING_LINE_COUNT + { + // a page has been computed + return 1; + } + } - // prepare for next line - start += len; + // prepare for next line + start += len; - // skip to next line/page - line++; - if ( + // skip to next line/page + line++; + if ( #if UX_LAYOUT_PAGING_LINE_COUNT > 1 - line >= UX_LAYOUT_PAGING_LINE_COUNT && -#endif // UX_LAYOUT_PAGING_LINE_COUNT - start < end) { - page++; - line = 0; + line >= UX_LAYOUT_PAGING_LINE_COUNT && +#endif // UX_LAYOUT_PAGING_LINE_COUNT + start < end) { + page++; + line = 0; + } } - } - // return total number of page detected - return page+1; + // return total number of page detected + return page + 1; } -#endif // HAVE_BAGL -#endif // HAVE_UX_FLOW +#endif // HAVE_BAGL +#endif // HAVE_UX_FLOW diff --git a/lib_ux/src/ux_layout_pb.c b/lib_ux/src/ux_layout_pb.c index e7cb246ae..7b2cd6f7c 100644 --- a/lib_ux/src/ux_layout_pb.c +++ b/lib_ux/src/ux_layout_pb.c @@ -1,20 +1,20 @@ /******************************************************************************* -* Ledger Nano S - Secure firmware -* (c) 2022 Ledger -* -* Licensed under the Apache License, Version 2.0 (the "License"); -* you may not use this file except in compliance with the License. -* You may obtain a copy of the License at -* -* http://www.apache.org/licenses/LICENSE-2.0 -* -* Unless required by applicable law or agreed to in writing, software -* distributed under the License is distributed on an "AS IS" BASIS, -* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -* See the License for the specific language governing permissions and -* limitations under the License. -********************************************************************************/ + * Ledger Nano S - Secure firmware + * (c) 2022 Ledger + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT 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 "ux.h" #include "os_utils.h" @@ -23,6 +23,7 @@ #include +// clang-format off const bagl_element_t ux_layout_pb_elements[] = { #if (BAGL_WIDTH==128 && BAGL_HEIGHT==64) @@ -56,55 +57,60 @@ const bagl_element_t ux_layout_pb_elements[] = { #error "BAGL_WIDTH/BAGL_HEIGHT not defined" #endif }; - -const bagl_element_t* ux_layout_pb_prepro(const bagl_element_t* element) { - // don't display if null - const void *params = ux_stack_get_current_step_params(); - - // copy element before any mod - memmove(&G_ux.tmp_element, element, sizeof(bagl_element_t)); - - // for dashboard, setup the current application's name - switch (element->component.userid) { - case 0x01: - if (ux_flow_is_first()) { - return NULL; - } - break; - - case 0x02: - if (ux_flow_is_last()) { - return NULL; - } - break; - - case 0x10: +// clang-format on + +const bagl_element_t *ux_layout_pb_prepro(const bagl_element_t *element) +{ + // don't display if null + const void *params = ux_stack_get_current_step_params(); + + // copy element before any mod + memmove(&G_ux.tmp_element, element, sizeof(bagl_element_t)); + + // for dashboard, setup the current application's name + switch (element->component.userid) { + case 0x01: + if (ux_flow_is_first()) { + return NULL; + } + break; + + case 0x02: + if (ux_flow_is_last()) { + return NULL; + } + break; + + case 0x10: #if defined(HAVE_INDEXED_STRINGS) - G_ux.tmp_element.text = (const char*)(((const ux_loc_layout_icon_params_t*)params)->icon); -#else //defined(HAVE_INDEXED_STRINGS) - G_ux.tmp_element.text = (const char*)(((const ux_layout_pb_params_t*)params)->icon); -#endif //defined(HAVE_INDEXED_STRINGS) - break; - - case 0x11: + G_ux.tmp_element.text + = (const char *) (((const ux_loc_layout_icon_params_t *) params)->icon); +#else // defined(HAVE_INDEXED_STRINGS) + G_ux.tmp_element.text = (const char *) (((const ux_layout_pb_params_t *) params)->icon); +#endif // defined(HAVE_INDEXED_STRINGS) + break; + + case 0x11: #if defined(HAVE_INDEXED_STRINGS) - G_ux.tmp_element.text = get_ux_loc_string(((const ux_loc_layout_icon_params_t*)params)->index); -#else //defined(HAVE_INDEXED_STRINGS) - G_ux.tmp_element.text = ((const ux_layout_pb_params_t*)params)->line1; -#endif //defined(HAVE_INDEXED_STRINGS) - break; - } - return &G_ux.tmp_element; + G_ux.tmp_element.text + = get_ux_loc_string(((const ux_loc_layout_icon_params_t *) params)->index); +#else // defined(HAVE_INDEXED_STRINGS) + G_ux.tmp_element.text = ((const ux_layout_pb_params_t *) params)->line1; +#endif // defined(HAVE_INDEXED_STRINGS) + break; + } + return &G_ux.tmp_element; } -void ux_layout_pb_init(unsigned int stack_slot) { - ux_stack_init(stack_slot); - G_ux.stack[stack_slot].element_arrays[0].element_array = ux_layout_pb_elements; - G_ux.stack[stack_slot].element_arrays[0].element_array_count = ARRAYLEN(ux_layout_pb_elements); - G_ux.stack[stack_slot].element_arrays_count = 1; - G_ux.stack[stack_slot].screen_before_element_display_callback = ux_layout_pb_prepro; - G_ux.stack[stack_slot].button_push_callback = ux_flow_button_callback; - ux_stack_display(stack_slot); +void ux_layout_pb_init(unsigned int stack_slot) +{ + ux_stack_init(stack_slot); + G_ux.stack[stack_slot].element_arrays[0].element_array = ux_layout_pb_elements; + G_ux.stack[stack_slot].element_arrays[0].element_array_count = ARRAYLEN(ux_layout_pb_elements); + G_ux.stack[stack_slot].element_arrays_count = 1; + G_ux.stack[stack_slot].screen_before_element_display_callback = ux_layout_pb_prepro; + G_ux.stack[stack_slot].button_push_callback = ux_flow_button_callback; + ux_stack_display(stack_slot); } -#endif // HAVE_UX_FLOW +#endif // HAVE_UX_FLOW diff --git a/lib_ux/src/ux_layout_pbb.c b/lib_ux/src/ux_layout_pbb.c index cd8f2ea3e..cb3a13961 100644 --- a/lib_ux/src/ux_layout_pbb.c +++ b/lib_ux/src/ux_layout_pbb.c @@ -1,20 +1,20 @@ /******************************************************************************* -* Ledger Nano S - Secure firmware -* (c) 2022 Ledger -* -* Licensed under the Apache License, Version 2.0 (the "License"); -* you may not use this file except in compliance with the License. -* You may obtain a copy of the License at -* -* http://www.apache.org/licenses/LICENSE-2.0 -* -* Unless required by applicable law or agreed to in writing, software -* distributed under the License is distributed on an "AS IS" BASIS, -* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -* See the License for the specific language governing permissions and -* limitations under the License. -********************************************************************************/ + * Ledger Nano S - Secure firmware + * (c) 2022 Ledger + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT 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 "ux.h" #include "os_utils.h" @@ -27,6 +27,7 @@ * 4 text lines */ +// clang-format off const bagl_element_t ux_layout_pbb_elements[] = { #if (BAGL_WIDTH==128 && BAGL_HEIGHT==64) // erase @@ -54,63 +55,70 @@ const bagl_element_t ux_layout_pbb_elements[] = { #error "BAGL_WIDTH/BAGL_HEIGHT not defined" #endif }; - -const bagl_element_t* ux_layout_pbb_prepro(const bagl_element_t* element) { - // don't display if null - const void *params = ux_stack_get_current_step_params(); - - // copy element before any mod - memmove(&G_ux.tmp_element, element, sizeof(bagl_element_t)); - - // for dashboard, setup the current application's name - switch (element->component.userid) { - case 0x01: - if (ux_flow_is_first()) { - return NULL; - } - break; - - case 0x02: - if (ux_flow_is_last()) { - return NULL; - } - break; - - case 0x0F: +// clang-format on + +const bagl_element_t *ux_layout_pbb_prepro(const bagl_element_t *element) +{ + // don't display if null + const void *params = ux_stack_get_current_step_params(); + + // copy element before any mod + memmove(&G_ux.tmp_element, element, sizeof(bagl_element_t)); + + // for dashboard, setup the current application's name + switch (element->component.userid) { + case 0x01: + if (ux_flow_is_first()) { + return NULL; + } + break; + + case 0x02: + if (ux_flow_is_last()) { + return NULL; + } + break; + + case 0x0F: #if defined(HAVE_INDEXED_STRINGS) - G_ux.tmp_element.text = (const char*)(((const ux_loc_layout_icon_params_t*)params)->icon); -#else //defined(HAVE_INDEXED_STRINGS) - G_ux.tmp_element.text = (const char*)(((const ux_layout_icon_strings_params_t*)params)->icon); -#endif //defined(HAVE_INDEXED_STRINGS) - break; - - case 0x10: - case 0x11: - { + G_ux.tmp_element.text + = (const char *) (((const ux_loc_layout_icon_params_t *) params)->icon); +#else // defined(HAVE_INDEXED_STRINGS) + G_ux.tmp_element.text + = (const char *) (((const ux_layout_icon_strings_params_t *) params)->icon); +#endif // defined(HAVE_INDEXED_STRINGS) + break; + + case 0x10: + case 0x11: { #if defined(HAVE_INDEXED_STRINGS) - UX_LOC_STRINGS_INDEX index = ((const ux_loc_layout_icon_params_t*)params)->index + (G_ux.tmp_element.component.userid&0xF); - G_ux.tmp_element.text = get_ux_loc_string(index); -#else //defined(HAVE_INDEXED_STRINGS) - G_ux.tmp_element.text = ((const ux_layout_icon_strings_params_t*)params)->lines[G_ux.tmp_element.component.userid&0xF]; -#endif //defined(HAVE_INDEXED_STRINGS) - break; + UX_LOC_STRINGS_INDEX index = ((const ux_loc_layout_icon_params_t *) params)->index + + (G_ux.tmp_element.component.userid & 0xF); + G_ux.tmp_element.text = get_ux_loc_string(index); +#else // defined(HAVE_INDEXED_STRINGS) + G_ux.tmp_element.text = ((const ux_layout_icon_strings_params_t *) params) + ->lines[G_ux.tmp_element.component.userid & 0xF]; +#endif // defined(HAVE_INDEXED_STRINGS) + break; + } } - } - return &G_ux.tmp_element; + return &G_ux.tmp_element; } -void ux_layout_pbb_init_common(unsigned int stack_slot) { - ux_stack_init(stack_slot); - G_ux.stack[stack_slot].element_arrays[0].element_array = ux_layout_pbb_elements; - G_ux.stack[stack_slot].element_arrays[0].element_array_count = ARRAYLEN(ux_layout_pbb_elements); - G_ux.stack[stack_slot].element_arrays_count = 1; - G_ux.stack[stack_slot].button_push_callback = ux_flow_button_callback; +void ux_layout_pbb_init_common(unsigned int stack_slot) +{ + ux_stack_init(stack_slot); + G_ux.stack[stack_slot].element_arrays[0].element_array = ux_layout_pbb_elements; + G_ux.stack[stack_slot].element_arrays[0].element_array_count = ARRAYLEN(ux_layout_pbb_elements); + G_ux.stack[stack_slot].element_arrays_count = 1; + G_ux.stack[stack_slot].button_push_callback = ux_flow_button_callback; } -void ux_layout_pbb_init(unsigned int stack_slot) { - ux_layout_pbb_init_common(stack_slot); - G_ux.stack[stack_slot].screen_before_element_display_callback = ux_layout_pbb_prepro; - ux_stack_display(stack_slot); +void ux_layout_pbb_init(unsigned int stack_slot) +{ + ux_layout_pbb_init_common(stack_slot); + G_ux.stack[stack_slot].screen_before_element_display_callback = ux_layout_pbb_prepro; + ux_stack_display(stack_slot); } -#endif // HAVE_UX_FLOW +#endif // HAVE_UX_FLOW diff --git a/lib_ux/src/ux_layout_pbn.c b/lib_ux/src/ux_layout_pbn.c index 5cc2e6b64..e7ec5352c 100644 --- a/lib_ux/src/ux_layout_pbn.c +++ b/lib_ux/src/ux_layout_pbn.c @@ -1,45 +1,48 @@ /******************************************************************************* -* Ledger Nano S - Secure firmware -* (c) 2022 Ledger -* -* Licensed under the Apache License, Version 2.0 (the "License"); -* you may not use this file except in compliance with the License. -* You may obtain a copy of the License at -* -* http://www.apache.org/licenses/LICENSE-2.0 -* -* Unless required by applicable law or agreed to in writing, software -* distributed under the License is distributed on an "AS IS" BASIS, -* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -* See the License for the specific language governing permissions and -* limitations under the License. -********************************************************************************/ + * Ledger Nano S - Secure firmware + * (c) 2022 Ledger + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT 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 "ux.h" #include "ux_layout_common.h" #ifdef HAVE_UX_FLOW -const bagl_element_t* ux_layout_pbn_prepro(const bagl_element_t* element) { - const bagl_element_t* e = ux_layout_pbb_prepro(element); - if (e && G_ux.tmp_element.component.userid == 0x11) { - // The centering depends on the target. -#if (BAGL_WIDTH==128 && BAGL_HEIGHT==64) - G_ux.tmp_element.component.font_id = BAGL_FONT_OPEN_SANS_REGULAR_11px|BAGL_FONT_ALIGNMENT_CENTER; -#elif (BAGL_WIDTH==128 && BAGL_HEIGHT==32) - G_ux.tmp_element.component.font_id = BAGL_FONT_OPEN_SANS_REGULAR_11px; +const bagl_element_t *ux_layout_pbn_prepro(const bagl_element_t *element) +{ + const bagl_element_t *e = ux_layout_pbb_prepro(element); + if (e && G_ux.tmp_element.component.userid == 0x11) { + // The centering depends on the target. +#if (BAGL_WIDTH == 128 && BAGL_HEIGHT == 64) + G_ux.tmp_element.component.font_id + = BAGL_FONT_OPEN_SANS_REGULAR_11px | BAGL_FONT_ALIGNMENT_CENTER; +#elif (BAGL_WIDTH == 128 && BAGL_HEIGHT == 32) + G_ux.tmp_element.component.font_id = BAGL_FONT_OPEN_SANS_REGULAR_11px; #else - #error "BAGL_WIDTH/BAGL_HEIGHT not defined" +#error "BAGL_WIDTH/BAGL_HEIGHT not defined" #endif - } - return e; + } + return e; } -void ux_layout_pbn_init(unsigned int stack_slot) { - ux_layout_pbb_init_common(stack_slot); - G_ux.stack[stack_slot].screen_before_element_display_callback = ux_layout_pbn_prepro; - ux_stack_display(stack_slot); +void ux_layout_pbn_init(unsigned int stack_slot) +{ + ux_layout_pbb_init_common(stack_slot); + G_ux.stack[stack_slot].screen_before_element_display_callback = ux_layout_pbn_prepro; + ux_stack_display(stack_slot); } -#endif // HAVE_UX_FLOW +#endif // HAVE_UX_FLOW diff --git a/lib_ux/src/ux_layout_pn.c b/lib_ux/src/ux_layout_pn.c index c5fd0fd6b..ddb4a9ee9 100644 --- a/lib_ux/src/ux_layout_pn.c +++ b/lib_ux/src/ux_layout_pn.c @@ -1,20 +1,20 @@ /******************************************************************************* -* Ledger Nano S - Secure firmware -* (c) 2022 Ledger -* -* Licensed under the Apache License, Version 2.0 (the "License"); -* you may not use this file except in compliance with the License. -* You may obtain a copy of the License at -* -* http://www.apache.org/licenses/LICENSE-2.0 -* -* Unless required by applicable law or agreed to in writing, software -* distributed under the License is distributed on an "AS IS" BASIS, -* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -* See the License for the specific language governing permissions and -* limitations under the License. -********************************************************************************/ + * Ledger Nano S - Secure firmware + * (c) 2022 Ledger + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT 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 "ux.h" #include "os_utils.h" @@ -22,6 +22,7 @@ #ifdef HAVE_UX_FLOW +// clang-format off const bagl_element_t ux_layout_pn_elements[] = { #if (BAGL_WIDTH==128 && BAGL_HEIGHT==64) // erase @@ -46,17 +47,19 @@ const bagl_element_t ux_layout_pn_elements[] = { #error "BAGL_WIDTH/BAGL_HEIGHT not defined" #endif }; +// clang-format on -const bagl_element_t* ux_layout_pb_prepro(const bagl_element_t* element); +const bagl_element_t *ux_layout_pb_prepro(const bagl_element_t *element); -void ux_layout_pn_init(unsigned int stack_slot) { - ux_stack_init(stack_slot); - G_ux.stack[stack_slot].element_arrays[0].element_array = ux_layout_pn_elements; - G_ux.stack[stack_slot].element_arrays[0].element_array_count = ARRAYLEN(ux_layout_pn_elements); - G_ux.stack[stack_slot].element_arrays_count = 1; - G_ux.stack[stack_slot].screen_before_element_display_callback = ux_layout_pb_prepro; - G_ux.stack[stack_slot].button_push_callback = ux_flow_button_callback; - ux_stack_display(stack_slot); +void ux_layout_pn_init(unsigned int stack_slot) +{ + ux_stack_init(stack_slot); + G_ux.stack[stack_slot].element_arrays[0].element_array = ux_layout_pn_elements; + G_ux.stack[stack_slot].element_arrays[0].element_array_count = ARRAYLEN(ux_layout_pn_elements); + G_ux.stack[stack_slot].element_arrays_count = 1; + G_ux.stack[stack_slot].screen_before_element_display_callback = ux_layout_pb_prepro; + G_ux.stack[stack_slot].button_push_callback = ux_flow_button_callback; + ux_stack_display(stack_slot); } -#endif // HAVE_UX_FLOW +#endif // HAVE_UX_FLOW diff --git a/lib_ux/src/ux_layout_pnn.c b/lib_ux/src/ux_layout_pnn.c index 25bdef245..8758c7ce1 100644 --- a/lib_ux/src/ux_layout_pnn.c +++ b/lib_ux/src/ux_layout_pnn.c @@ -1,20 +1,20 @@ /******************************************************************************* -* Ledger Nano S - Secure firmware -* (c) 2022 Ledger -* -* Licensed under the Apache License, Version 2.0 (the "License"); -* you may not use this file except in compliance with the License. -* You may obtain a copy of the License at -* -* http://www.apache.org/licenses/LICENSE-2.0 -* -* Unless required by applicable law or agreed to in writing, software -* distributed under the License is distributed on an "AS IS" BASIS, -* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -* See the License for the specific language governing permissions and -* limitations under the License. -********************************************************************************/ + * Ledger Nano S - Secure firmware + * (c) 2022 Ledger + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT 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 "ux.h" #include "ux_layout_common.h" @@ -25,25 +25,28 @@ * 4 text lines */ -const bagl_element_t* ux_layout_pnn_prepro(const bagl_element_t* element) { - const bagl_element_t* e = ux_layout_pbb_prepro(element); - if (e && G_ux.tmp_element.component.userid >= 0x10) { - // The centering depends on the screensize. -#if (BAGL_WIDTH==128 && BAGL_HEIGHT==64) - G_ux.tmp_element.component.font_id = BAGL_FONT_OPEN_SANS_REGULAR_11px|BAGL_FONT_ALIGNMENT_CENTER; -#elif (BAGL_WIDTH==128 && BAGL_HEIGHT==32) - G_ux.tmp_element.component.font_id = BAGL_FONT_OPEN_SANS_REGULAR_11px; +const bagl_element_t *ux_layout_pnn_prepro(const bagl_element_t *element) +{ + const bagl_element_t *e = ux_layout_pbb_prepro(element); + if (e && G_ux.tmp_element.component.userid >= 0x10) { + // The centering depends on the screensize. +#if (BAGL_WIDTH == 128 && BAGL_HEIGHT == 64) + G_ux.tmp_element.component.font_id + = BAGL_FONT_OPEN_SANS_REGULAR_11px | BAGL_FONT_ALIGNMENT_CENTER; +#elif (BAGL_WIDTH == 128 && BAGL_HEIGHT == 32) + G_ux.tmp_element.component.font_id = BAGL_FONT_OPEN_SANS_REGULAR_11px; #else - #error "BAGL_WIDTH/BAGL_HEIGHT not defined" +#error "BAGL_WIDTH/BAGL_HEIGHT not defined" #endif - } - return e; + } + return e; } -void ux_layout_pnn_init(unsigned int stack_slot) { - ux_layout_pbb_init_common(stack_slot); - G_ux.stack[stack_slot].screen_before_element_display_callback = ux_layout_pnn_prepro; - ux_stack_display(stack_slot); +void ux_layout_pnn_init(unsigned int stack_slot) +{ + ux_layout_pbb_init_common(stack_slot); + G_ux.stack[stack_slot].screen_before_element_display_callback = ux_layout_pnn_prepro; + ux_stack_display(stack_slot); } -#endif // HAVE_UX_FLOW +#endif // HAVE_UX_FLOW diff --git a/lib_ux/src/ux_layout_utils.c b/lib_ux/src/ux_layout_utils.c index 30c6a327e..ff1ffcd45 100644 --- a/lib_ux/src/ux_layout_utils.c +++ b/lib_ux/src/ux_layout_utils.c @@ -1,20 +1,20 @@ /******************************************************************************* -* Ledger Nano S - Secure firmware -* (c) 2022 Ledger -* -* Licensed under the Apache License, Version 2.0 (the "License"); -* you may not use this file except in compliance with the License. -* You may obtain a copy of the License at -* -* http://www.apache.org/licenses/LICENSE-2.0 -* -* Unless required by applicable law or agreed to in writing, software -* distributed under the License is distributed on an "AS IS" BASIS, -* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -* See the License for the specific language governing permissions and -* limitations under the License. -********************************************************************************/ + * Ledger Nano S - Secure firmware + * (c) 2022 Ledger + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT 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 "ux.h" #include "os_helpers.h" @@ -24,61 +24,65 @@ #include -static unsigned int ux_layout_ticker_callback(unsigned int unused) { - UNUSED(unused); - // when the callback is called, then the slot is forcefully the top of stack - G_ux.stack[G_ux.stack_count-1].ticker_interval = 0; - G_ux.stack[G_ux.stack_count-1].ticker_value = 0; - G_ux.stack[G_ux.stack_count-1].ticker_callback = NULL; - // auto validate the step - ux_flow_validate(); - return 0; +static unsigned int ux_layout_ticker_callback(unsigned int unused) +{ + UNUSED(unused); + // when the callback is called, then the slot is forcefully the top of stack + G_ux.stack[G_ux.stack_count - 1].ticker_interval = 0; + G_ux.stack[G_ux.stack_count - 1].ticker_value = 0; + G_ux.stack[G_ux.stack_count - 1].ticker_callback = NULL; + // auto validate the step + ux_flow_validate(); + return 0; } -void ux_layout_set_timeout(unsigned int stack_slot, unsigned int ms) { - if (ms) { - G_ux.stack[stack_slot].ticker_callback = ux_layout_ticker_callback; - G_ux.stack[stack_slot].ticker_value = ms; - G_ux.stack[stack_slot].ticker_interval = ms; // restart - } +void ux_layout_set_timeout(unsigned int stack_slot, unsigned int ms) +{ + if (ms) { + G_ux.stack[stack_slot].ticker_callback = ux_layout_ticker_callback; + G_ux.stack[stack_slot].ticker_value = ms; + G_ux.stack[stack_slot].ticker_interval = ms; // restart + } } -const bagl_element_t* ux_layout_strings_prepro(const bagl_element_t* element) { - // don't display if null - const void *params = ux_stack_get_current_step_params(); +const bagl_element_t *ux_layout_strings_prepro(const bagl_element_t *element) +{ + // don't display if null + const void *params = ux_stack_get_current_step_params(); - // copy element before any mod - memmove(&G_ux.tmp_element, element, sizeof(bagl_element_t)); + // copy element before any mod + memmove(&G_ux.tmp_element, element, sizeof(bagl_element_t)); - // for dashboard, setup the current application's name - switch (element->component.userid) { - case 0x01: - if (ux_flow_is_first()) { - return NULL; - } - break; + // for dashboard, setup the current application's name + switch (element->component.userid) { + case 0x01: + if (ux_flow_is_first()) { + return NULL; + } + break; - case 0x02: - if (ux_flow_is_last()) { - return NULL; - } - break; + case 0x02: + if (ux_flow_is_last()) { + return NULL; + } + break; - default: - { - if (G_ux.tmp_element.component.userid&0xF0) { + default: { + if (G_ux.tmp_element.component.userid & 0xF0) { #if defined(HAVE_INDEXED_STRINGS) - UX_LOC_STRINGS_INDEX index = ((const ux_loc_layout_params_t*)params)->index + (G_ux.tmp_element.component.userid&0xF); - // NB: it will call the BOLOS version of the function when linked with - // BOLOS, and the app version when linked with the app! - G_ux.tmp_element.text = get_ux_loc_string(index); -#else //defined(HAVE_INDEXED_STRINGS) - G_ux.tmp_element.text = ((const ux_layout_strings_params_t*)params)->lines[G_ux.tmp_element.component.userid&0xF]; -#endif //defined(HAVE_INDEXED_STRINGS) - } - break; + UX_LOC_STRINGS_INDEX index = ((const ux_loc_layout_params_t *) params)->index + + (G_ux.tmp_element.component.userid & 0xF); + // NB: it will call the BOLOS version of the function when linked with + // BOLOS, and the app version when linked with the app! + G_ux.tmp_element.text = get_ux_loc_string(index); +#else // defined(HAVE_INDEXED_STRINGS) + G_ux.tmp_element.text = ((const ux_layout_strings_params_t *) params) + ->lines[G_ux.tmp_element.component.userid & 0xF]; +#endif // defined(HAVE_INDEXED_STRINGS) + } + break; + } } - } - return &G_ux.tmp_element; + return &G_ux.tmp_element; } -#endif // HAVE_UX_FLOW +#endif // HAVE_UX_FLOW diff --git a/lib_ux/src/ux_legacy.c b/lib_ux/src/ux_legacy.c index 1b330bdd5..27f74615e 100644 --- a/lib_ux/src/ux_legacy.c +++ b/lib_ux/src/ux_legacy.c @@ -1,20 +1,20 @@ /******************************************************************************* -* Ledger Nano S - Secure firmware -* (c) 2022 Ledger -* -* Licensed under the Apache License, Version 2.0 (the "License"); -* you may not use this file except in compliance with the License. -* You may obtain a copy of the License at -* -* http://www.apache.org/licenses/LICENSE-2.0 -* -* Unless required by applicable law or agreed to in writing, software -* distributed under the License is distributed on an "AS IS" BASIS, -* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -* See the License for the specific language governing permissions and -* limitations under the License. -********************************************************************************/ + * Ledger Nano S - Secure firmware + * (c) 2022 Ledger + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT 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 "ux.h" #include "os_helpers.h" @@ -24,9 +24,10 @@ #include #ifdef HAVE_UX_LEGACY -ux_menu_state_t ux_menu; +ux_menu_state_t ux_menu; ux_turner_state_t ux_turner; +// clang-format off const bagl_element_t ux_menu_elements[] = { // erase {{BAGL_RECTANGLE , 0x80, 0, 0, 128, 32, 0, 0, BAGL_FILL, 0x000000, 0xFFFFFF, 0, 0}, .text=NULL}, @@ -50,216 +51,223 @@ const bagl_element_t ux_menu_elements[] = { {{BAGL_LABELINE , 0x22, 14, 26, 100, 12, 0, 0, 0 , 0xFFFFFF, 0x000000, BAGL_FONT_OPEN_SANS_EXTRABOLD_11px|BAGL_FONT_ALIGNMENT_CENTER, 0 }, .text=NULL }, }; +// clang-format on -const ux_menu_entry_t* ux_menu_get_entry (unsigned int entry_idx) { - if (ux_menu.menu_iterator) { - return ux_menu.menu_iterator(entry_idx); - } - return &ux_menu.menu_entries[entry_idx]; +const ux_menu_entry_t *ux_menu_get_entry(unsigned int entry_idx) +{ + if (ux_menu.menu_iterator) { + return ux_menu.menu_iterator(entry_idx); + } + return &ux_menu.menu_entries[entry_idx]; } -const bagl_element_t* ux_menu_element_preprocessor(const bagl_element_t* element) { - //todo avoid center alignment when text_x or icon_x AND text_x are not 0 - memmove(&G_ux.tmp_element, element, sizeof(bagl_element_t)); - - // ask the current entry first, to setup other entries - const ux_menu_entry_t* current_entry = (const ux_menu_entry_t*)PIC(ux_menu_get_entry(ux_menu.current_entry)); - if (current_entry == NULL) { - return NULL; - } - const bagl_icon_details_t* current_entry_icon = (const bagl_icon_details_t*)PIC(current_entry->icon); - - const ux_menu_entry_t* previous_entry = NULL; - if (ux_menu.current_entry) { - previous_entry = (const ux_menu_entry_t*)PIC(ux_menu_get_entry(ux_menu.current_entry-1)); - } - const ux_menu_entry_t* next_entry = NULL; - if (ux_menu.current_entry < ux_menu.menu_entries_count-1) { - next_entry = (const ux_menu_entry_t*)PIC(ux_menu_get_entry(ux_menu.current_entry+1)); - } - - switch(element->component.userid) { - case 0x81: - if (ux_menu.current_entry == 0) { - return NULL; - } - break; - case 0x82: - if (ux_menu.current_entry == ux_menu.menu_entries_count-1) { - return NULL; - } - break; - // previous setting name - case 0x41: - if (current_entry->line2 != NULL - || current_entry->icon != NULL - || ux_menu.current_entry == 0 - || ux_menu.menu_entries_count == 1 - || !previous_entry - || previous_entry->icon != NULL - || previous_entry->line2 != NULL) { - return 0; - } - G_ux.tmp_element.text = previous_entry->line1; - break; - // next setting name - case 0x42: - if (current_entry->line2 != NULL - || current_entry->icon != NULL - || ux_menu.current_entry == ux_menu.menu_entries_count-1 - || ux_menu.menu_entries_count == 1 - || !next_entry - || next_entry->icon != NULL) { - return NULL; - } - G_ux.tmp_element.text = next_entry->line1; - break; - case 0x10: - if (current_entry->icon == NULL) { - return NULL; - } - G_ux.tmp_element.text = (const char*)current_entry->icon; - if (current_entry->icon_x) { - G_ux.tmp_element.component.x = current_entry->icon_x; - } - break; - case 0x20: - if (current_entry->line2 != NULL) { - return NULL; - } - G_ux.tmp_element.text = current_entry->line1; - goto adjust_text_x; - case 0x21: - if (current_entry->line2 == NULL) { - return NULL; - } - G_ux.tmp_element.text = current_entry->line1; - goto adjust_text_x; - case 0x22: - if (current_entry->line2 == NULL) { +const bagl_element_t *ux_menu_element_preprocessor(const bagl_element_t *element) +{ + // todo avoid center alignment when text_x or icon_x AND text_x are not 0 + memmove(&G_ux.tmp_element, element, sizeof(bagl_element_t)); + + // ask the current entry first, to setup other entries + const ux_menu_entry_t *current_entry + = (const ux_menu_entry_t *) PIC(ux_menu_get_entry(ux_menu.current_entry)); + if (current_entry == NULL) { return NULL; - } - G_ux.tmp_element.text = current_entry->line2; - adjust_text_x: - if (current_entry_icon) { - G_ux.tmp_element.component.x += current_entry_icon->width; - G_ux.tmp_element.component.width -= current_entry_icon->width; - } - if (current_entry->text_x) { - G_ux.tmp_element.component.x = current_entry->text_x; - // discard the 'center' flag - G_ux.tmp_element.component.font_id = BAGL_FONT_OPEN_SANS_EXTRABOLD_11px; - } - break; - } - // ensure prepro agrees to the element to be displayed - if (ux_menu.menu_entry_preprocessor) { - // menu is denied by the menu entry preprocessor - return ux_menu.menu_entry_preprocessor(current_entry, &G_ux.tmp_element); - } - - return &G_ux.tmp_element; + } + const bagl_icon_details_t *current_entry_icon + = (const bagl_icon_details_t *) PIC(current_entry->icon); + + const ux_menu_entry_t *previous_entry = NULL; + if (ux_menu.current_entry) { + previous_entry + = (const ux_menu_entry_t *) PIC(ux_menu_get_entry(ux_menu.current_entry - 1)); + } + const ux_menu_entry_t *next_entry = NULL; + if (ux_menu.current_entry < ux_menu.menu_entries_count - 1) { + next_entry = (const ux_menu_entry_t *) PIC(ux_menu_get_entry(ux_menu.current_entry + 1)); + } + + switch (element->component.userid) { + case 0x81: + if (ux_menu.current_entry == 0) { + return NULL; + } + break; + case 0x82: + if (ux_menu.current_entry == ux_menu.menu_entries_count - 1) { + return NULL; + } + break; + // previous setting name + case 0x41: + if (current_entry->line2 != NULL || current_entry->icon != NULL + || ux_menu.current_entry == 0 || ux_menu.menu_entries_count == 1 || !previous_entry + || previous_entry->icon != NULL || previous_entry->line2 != NULL) { + return 0; + } + G_ux.tmp_element.text = previous_entry->line1; + break; + // next setting name + case 0x42: + if (current_entry->line2 != NULL || current_entry->icon != NULL + || ux_menu.current_entry == ux_menu.menu_entries_count - 1 + || ux_menu.menu_entries_count == 1 || !next_entry || next_entry->icon != NULL) { + return NULL; + } + G_ux.tmp_element.text = next_entry->line1; + break; + case 0x10: + if (current_entry->icon == NULL) { + return NULL; + } + G_ux.tmp_element.text = (const char *) current_entry->icon; + if (current_entry->icon_x) { + G_ux.tmp_element.component.x = current_entry->icon_x; + } + break; + case 0x20: + if (current_entry->line2 != NULL) { + return NULL; + } + G_ux.tmp_element.text = current_entry->line1; + goto adjust_text_x; + case 0x21: + if (current_entry->line2 == NULL) { + return NULL; + } + G_ux.tmp_element.text = current_entry->line1; + goto adjust_text_x; + case 0x22: + if (current_entry->line2 == NULL) { + return NULL; + } + G_ux.tmp_element.text = current_entry->line2; + adjust_text_x: + if (current_entry_icon) { + G_ux.tmp_element.component.x += current_entry_icon->width; + G_ux.tmp_element.component.width -= current_entry_icon->width; + } + if (current_entry->text_x) { + G_ux.tmp_element.component.x = current_entry->text_x; + // discard the 'center' flag + G_ux.tmp_element.component.font_id = BAGL_FONT_OPEN_SANS_EXTRABOLD_11px; + } + break; + } + // ensure prepro agrees to the element to be displayed + if (ux_menu.menu_entry_preprocessor) { + // menu is denied by the menu entry preprocessor + return ux_menu.menu_entry_preprocessor(current_entry, &G_ux.tmp_element); + } + + return &G_ux.tmp_element; } -unsigned int ux_menu_elements_button (unsigned int button_mask, unsigned int button_mask_counter) { - UNUSED(button_mask_counter); +unsigned int ux_menu_elements_button(unsigned int button_mask, unsigned int button_mask_counter) +{ + UNUSED(button_mask_counter); - const ux_menu_entry_t* current_entry = (const ux_menu_entry_t*)PIC(ux_menu_get_entry(ux_menu.current_entry)); - if (current_entry == NULL) { - return 1; - } - - switch (button_mask) { - // enter menu or exit menu - case BUTTON_EVT_RELEASED|BUTTON_LEFT|BUTTON_RIGHT: - // menu is priority 1 - if (current_entry->menu) { - // use userid as the pointer to current entry in the parent menu - UX_MENU_DISPLAY(current_entry->userid, (const ux_menu_entry_t*)PIC(current_entry->menu), ux_menu.menu_entry_preprocessor); - return 0; - } - // else callback - else if (current_entry->callback) { - ((ux_menu_callback_t)PIC(current_entry->callback))(current_entry->userid); - return 0; - } - break; - - case BUTTON_EVT_FAST|BUTTON_LEFT: - case BUTTON_EVT_RELEASED|BUTTON_LEFT: - // entry 0 is the number of entries in the menu list - if (ux_menu.current_entry == 0) { - return 0; - } - ux_menu.current_entry--; - goto redraw; - - case BUTTON_EVT_FAST|BUTTON_RIGHT: - case BUTTON_EVT_RELEASED|BUTTON_RIGHT: - // entry 0 is the number of entries in the menu list - if (ux_menu.current_entry >= ux_menu.menu_entries_count-1) { - return 0; - } - ux_menu.current_entry++; - redraw: + const ux_menu_entry_t *current_entry + = (const ux_menu_entry_t *) PIC(ux_menu_get_entry(ux_menu.current_entry)); + if (current_entry == NULL) { + return 1; + } + + switch (button_mask) { + // enter menu or exit menu + case BUTTON_EVT_RELEASED | BUTTON_LEFT | BUTTON_RIGHT: + // menu is priority 1 + if (current_entry->menu) { + // use userid as the pointer to current entry in the parent menu + UX_MENU_DISPLAY(current_entry->userid, + (const ux_menu_entry_t *) PIC(current_entry->menu), + ux_menu.menu_entry_preprocessor); + return 0; + } + // else callback + else if (current_entry->callback) { + ((ux_menu_callback_t) PIC(current_entry->callback))(current_entry->userid); + return 0; + } + break; + + case BUTTON_EVT_FAST | BUTTON_LEFT: + case BUTTON_EVT_RELEASED | BUTTON_LEFT: + // entry 0 is the number of entries in the menu list + if (ux_menu.current_entry == 0) { + return 0; + } + ux_menu.current_entry--; + goto redraw; + + case BUTTON_EVT_FAST | BUTTON_RIGHT: + case BUTTON_EVT_RELEASED | BUTTON_RIGHT: + // entry 0 is the number of entries in the menu list + if (ux_menu.current_entry >= ux_menu.menu_entries_count - 1) { + return 0; + } + ux_menu.current_entry++; + redraw: #ifdef HAVE_BOLOS_UX - ux_stack_display(0); + ux_stack_display(0); #else - UX_REDISPLAY(); + UX_REDISPLAY(); #endif - return 0; - } - return 1; + return 0; + } + return 1; } const ux_menu_entry_t UX_MENU_END_ENTRY = UX_MENU_END; -void ux_menu_display(unsigned int current_entry, - const ux_menu_entry_t* menu_entries, - ux_menu_preprocessor_t menu_entry_preprocessor) { - // reset to first entry - ux_menu.menu_entries_count = 0; - - // count entries - if (menu_entries) { - for(;;) { - if (memcmp(&menu_entries[ux_menu.menu_entries_count], &UX_MENU_END_ENTRY, sizeof(ux_menu_entry_t)) == 0) { - break; - } - ux_menu.menu_entries_count++; +void ux_menu_display(unsigned int current_entry, + const ux_menu_entry_t *menu_entries, + ux_menu_preprocessor_t menu_entry_preprocessor) +{ + // reset to first entry + ux_menu.menu_entries_count = 0; + + // count entries + if (menu_entries) { + for (;;) { + if (memcmp(&menu_entries[ux_menu.menu_entries_count], + &UX_MENU_END_ENTRY, + sizeof(ux_menu_entry_t)) + == 0) { + break; + } + ux_menu.menu_entries_count++; + } } - } - if (current_entry != UX_MENU_UNCHANGED_ENTRY) { - ux_menu.current_entry = current_entry; - if (ux_menu.current_entry > ux_menu.menu_entries_count) { - ux_menu.current_entry = 0; + if (current_entry != UX_MENU_UNCHANGED_ENTRY) { + ux_menu.current_entry = current_entry; + if (ux_menu.current_entry > ux_menu.menu_entries_count) { + ux_menu.current_entry = 0; + } } - } - ux_menu.menu_entries = menu_entries; - ux_menu.menu_entry_preprocessor = menu_entry_preprocessor; - ux_menu.menu_iterator = NULL; + ux_menu.menu_entries = menu_entries; + ux_menu.menu_entry_preprocessor = menu_entry_preprocessor; + ux_menu.menu_iterator = NULL; #ifdef HAVE_BOLOS_UX - ux_stack_init(0); + ux_stack_init(0); - // static dashboard content - G_ux.stack[0].element_arrays[0].element_array = ux_menu_elements; - G_ux.stack[0].element_arrays[0].element_array_count = ARRAYLEN(ux_menu_elements); - G_ux.stack[0].element_arrays_count = 1; + // static dashboard content + G_ux.stack[0].element_arrays[0].element_array = ux_menu_elements; + G_ux.stack[0].element_arrays[0].element_array_count = ARRAYLEN(ux_menu_elements); + G_ux.stack[0].element_arrays_count = 1; - // ensure the string_buffer will be set before each button is displayed - G_ux.stack[0].screen_before_element_display_callback = ux_menu_element_preprocessor; - G_ux.stack[0].button_push_callback = ux_menu_elements_button; + // ensure the string_buffer will be set before each button is displayed + G_ux.stack[0].screen_before_element_display_callback = ux_menu_element_preprocessor; + G_ux.stack[0].button_push_callback = ux_menu_elements_button; - ux_stack_display(0); + ux_stack_display(0); #else - // display the menu current entry - UX_DISPLAY(ux_menu_elements, ux_menu_element_preprocessor); + // display the menu current entry + UX_DISPLAY(ux_menu_elements, ux_menu_element_preprocessor); #endif } - +// clang-format off const bagl_element_t ux_turner_elements[] = { // erase {{BAGL_RECTANGLE , 0x00, 0, 0, 128, 32, 0, 0, BAGL_FILL, 0x000000, 0xFFFFFF, 0, 0}, .text=NULL}, @@ -278,178 +286,199 @@ const bagl_element_t ux_turner_elements[] = { {{BAGL_LABELINE , 0x06, 0, 26, 128, 32, 0, 0, 0 , 0xFFFFFF, 0x000000, BAGL_FONT_OPEN_SANS_REGULAR_11px|BAGL_FONT_ALIGNMENT_CENTER, 0 }, .text=NULL }, }; - -const bagl_element_t* ux_turner_element_preprocessor(const bagl_element_t* element) { - //todo avoid center alignment when text_x or icon_x AND text_x are not 0 - memmove(&G_ux.tmp_element, element, sizeof(bagl_element_t)); - - switch(element->component.userid) { - - case 0x03: - if (ux_turner.steps[ux_turner.current_step].icon == NULL) { - return NULL; - } - G_ux.tmp_element.text = (const char*)ux_turner.steps[ux_turner.current_step].icon; - if (ux_turner.steps[ux_turner.current_step].icon_x) { - G_ux.tmp_element.component.x = ux_turner.steps[ux_turner.current_step].icon_x; - } - break; - case 0x04: - if (ux_turner.steps[ux_turner.current_step].line2 != NULL) { - return NULL; - } - if (ux_turner.steps[ux_turner.current_step].fontid1) { - G_ux.tmp_element.component.font_id = ux_turner.steps[ux_turner.current_step].fontid1; - } - G_ux.tmp_element.text = ux_turner.steps[ux_turner.current_step].line1; - goto adjust_text_x; - case 0x05: - if (ux_turner.steps[ux_turner.current_step].line2 == NULL) { - return NULL; - } - if (ux_turner.steps[ux_turner.current_step].fontid1) { - G_ux.tmp_element.component.font_id = ux_turner.steps[ux_turner.current_step].fontid1; - } - G_ux.tmp_element.text = ux_turner.steps[ux_turner.current_step].line1; - goto adjust_text_x; - case 0x06: - if (ux_turner.steps[ux_turner.current_step].line2 == NULL) { - return NULL; - } - if (ux_turner.steps[ux_turner.current_step].fontid2) { - G_ux.tmp_element.component.font_id = ux_turner.steps[ux_turner.current_step].fontid2; - } - G_ux.tmp_element.text = ux_turner.steps[ux_turner.current_step].line2; - adjust_text_x: - if (ux_turner.steps[ux_turner.current_step].text_x) { - G_ux.tmp_element.component.x = ux_turner.steps[ux_turner.current_step].text_x; - } - break; - } - return &G_ux.tmp_element; +// clang-format on + +const bagl_element_t *ux_turner_element_preprocessor(const bagl_element_t *element) +{ + // todo avoid center alignment when text_x or icon_x AND text_x are not 0 + memmove(&G_ux.tmp_element, element, sizeof(bagl_element_t)); + + switch (element->component.userid) { + case 0x03: + if (ux_turner.steps[ux_turner.current_step].icon == NULL) { + return NULL; + } + G_ux.tmp_element.text = (const char *) ux_turner.steps[ux_turner.current_step].icon; + if (ux_turner.steps[ux_turner.current_step].icon_x) { + G_ux.tmp_element.component.x = ux_turner.steps[ux_turner.current_step].icon_x; + } + break; + case 0x04: + if (ux_turner.steps[ux_turner.current_step].line2 != NULL) { + return NULL; + } + if (ux_turner.steps[ux_turner.current_step].fontid1) { + G_ux.tmp_element.component.font_id + = ux_turner.steps[ux_turner.current_step].fontid1; + } + G_ux.tmp_element.text = ux_turner.steps[ux_turner.current_step].line1; + goto adjust_text_x; + case 0x05: + if (ux_turner.steps[ux_turner.current_step].line2 == NULL) { + return NULL; + } + if (ux_turner.steps[ux_turner.current_step].fontid1) { + G_ux.tmp_element.component.font_id + = ux_turner.steps[ux_turner.current_step].fontid1; + } + G_ux.tmp_element.text = ux_turner.steps[ux_turner.current_step].line1; + goto adjust_text_x; + case 0x06: + if (ux_turner.steps[ux_turner.current_step].line2 == NULL) { + return NULL; + } + if (ux_turner.steps[ux_turner.current_step].fontid2) { + G_ux.tmp_element.component.font_id + = ux_turner.steps[ux_turner.current_step].fontid2; + } + G_ux.tmp_element.text = ux_turner.steps[ux_turner.current_step].line2; + adjust_text_x: + if (ux_turner.steps[ux_turner.current_step].text_x) { + G_ux.tmp_element.component.x = ux_turner.steps[ux_turner.current_step].text_x; + } + break; + } + return &G_ux.tmp_element; } -unsigned int ux_turner_elements_button (unsigned int button_mask, unsigned int button_mask_counter) { - return ux_turner.button_callback(button_mask, button_mask_counter); +unsigned int ux_turner_elements_button(unsigned int button_mask, unsigned int button_mask_counter) +{ + return ux_turner.button_callback(button_mask, button_mask_counter); } #ifdef HAVE_BOLOS_UX -unsigned int ux_turner_ticker_bolos_ux(unsigned int ignored) { - UNUSED(ignored); - // switch to next step - ux_turner.current_step=(ux_turner.current_step+1)%ux_turner.steps_count; - // setup the next change - G_ux.stack[0].ticker_value = ux_turner.steps[ux_turner.current_step].next_step_ms; - G_ux.stack[0].ticker_interval = ux_turner.steps[ux_turner.current_step].next_step_ms; - ux_stack_display(0); - return 0; +unsigned int ux_turner_ticker_bolos_ux(unsigned int ignored) +{ + UNUSED(ignored); + // switch to next step + ux_turner.current_step = (ux_turner.current_step + 1) % ux_turner.steps_count; + // setup the next change + G_ux.stack[0].ticker_value = ux_turner.steps[ux_turner.current_step].next_step_ms; + G_ux.stack[0].ticker_interval = ux_turner.steps[ux_turner.current_step].next_step_ms; + ux_stack_display(0); + return 0; } #else -void ux_turner_ticker(unsigned int elapsed_ms) { - ux_turner.elapsed_ms -= MIN(ux_turner.elapsed_ms, elapsed_ms); - if (ux_turner.elapsed_ms == 0) { - // switch to next step - ux_turner.current_step=(ux_turner.current_step+1)%ux_turner.steps_count; - ux_turner.elapsed_ms = ux_turner.steps[ux_turner.current_step].next_step_ms; - UX_DISPLAY(ux_turner_elements, ux_turner_element_preprocessor); - } +void ux_turner_ticker(unsigned int elapsed_ms) +{ + ux_turner.elapsed_ms -= MIN(ux_turner.elapsed_ms, elapsed_ms); + if (ux_turner.elapsed_ms == 0) { + // switch to next step + ux_turner.current_step = (ux_turner.current_step + 1) % ux_turner.steps_count; + ux_turner.elapsed_ms = ux_turner.steps[ux_turner.current_step].next_step_ms; + UX_DISPLAY(ux_turner_elements, ux_turner_element_preprocessor); + } } -#endif // HAVE_BOLOS_UX - -void ux_turner_display(unsigned int current_step, - const ux_turner_step_t* steps, - unsigned int steps_count, - button_push_callback_t button_callback) { - // reset to first entry - ux_turner.steps_count = steps_count; - - if (current_step != UX_TURNER_UNCHANGED_ENTRY) { - ux_turner.current_step = current_step; - if (ux_turner.current_step > ux_turner.steps_count) { - ux_turner.current_step = 0; +#endif // HAVE_BOLOS_UX + +void ux_turner_display(unsigned int current_step, + const ux_turner_step_t *steps, + unsigned int steps_count, + button_push_callback_t button_callback) +{ + // reset to first entry + ux_turner.steps_count = steps_count; + + if (current_step != UX_TURNER_UNCHANGED_ENTRY) { + ux_turner.current_step = current_step; + if (ux_turner.current_step > ux_turner.steps_count) { + ux_turner.current_step = 0; + } } - } - ux_turner.steps = steps; + ux_turner.steps = steps; - ux_turner.button_callback = button_callback; + ux_turner.button_callback = button_callback; #ifdef HAVE_BOLOS_UX - ux_stack_init(0); + ux_stack_init(0); - // static dashboard content - G_ux.stack[0].element_arrays[0].element_array = ux_turner_elements; - G_ux.stack[0].element_arrays[0].element_array_count = ARRAYLEN(ux_turner_elements); - G_ux.stack[0].element_arrays_count = 1; + // static dashboard content + G_ux.stack[0].element_arrays[0].element_array = ux_turner_elements; + G_ux.stack[0].element_arrays[0].element_array_count = ARRAYLEN(ux_turner_elements); + G_ux.stack[0].element_arrays_count = 1; - // ensure the string_buffer will be set before each button is displayed - G_ux.stack[0].screen_before_element_display_callback = ux_turner_element_preprocessor; - G_ux.stack[0].button_push_callback = ux_turner_elements_button; - G_ux.stack[0].ticker_value = ux_turner.steps[ux_turner.current_step].next_step_ms; - G_ux.stack[0].ticker_interval = ux_turner.steps[ux_turner.current_step].next_step_ms; - G_ux.stack[0].ticker_callback = ux_turner_ticker_bolos_ux; + // ensure the string_buffer will be set before each button is displayed + G_ux.stack[0].screen_before_element_display_callback = ux_turner_element_preprocessor; + G_ux.stack[0].button_push_callback = ux_turner_elements_button; + G_ux.stack[0].ticker_value = ux_turner.steps[ux_turner.current_step].next_step_ms; + G_ux.stack[0].ticker_interval = ux_turner.steps[ux_turner.current_step].next_step_ms; + G_ux.stack[0].ticker_callback = ux_turner_ticker_bolos_ux; - ux_stack_display(0); + ux_stack_display(0); #else - ux_turner.elapsed_ms = ux_turner.steps[ux_turner.current_step].next_step_ms; - // display the menu current entry - UX_DISPLAY(ux_turner_elements, ux_turner_element_preprocessor); + ux_turner.elapsed_ms = ux_turner.steps[ux_turner.current_step].next_step_ms; + // display the menu current entry + UX_DISPLAY(ux_turner_elements, ux_turner_element_preprocessor); #endif } -#endif // HAVE_UX_LEGACY +#endif // HAVE_UX_LEGACY -const bagl_element_t clear_element = {{BAGL_RECTANGLE, 0, 0, 0, 128, 32, 0, 0, 0, 0x000000, 0x000000, 0 , 0},.text=NULL}; +const bagl_element_t clear_element = { + {BAGL_RECTANGLE, 0, 0, 0, 128, 32, 0, 0, 0, 0x000000, 0x000000, 0, 0}, + .text = NULL +}; -const bagl_element_t printf_element = {{BAGL_LABELINE, 0, 0, 9, 128, 32, 0, 0, 0, 0xFFFFFF, 0x000000, +const bagl_element_t printf_element = { + {BAGL_LABELINE, + 0, 0, + 9, 128, + 32, 0, + 0, 0, + 0xFFFFFF, 0x000000, #ifdef TARGET_NANOS - BAGL_FONT_OPEN_SANS_EXTRABOLD_11px | BAGL_FONT_ALIGNMENT_CENTER |BAGL_FONT_ALIGNMENT_MIDDLE -#else // TARGET_NANOS - BAGL_FONT_OPEN_SANS_REGULAR_8_11PX -#endif // TARGET_NANOS - , 0},.text="Default printf" - }; - -void debug_wait_displayed(void) { - // wait next event (probably a ticker, if not, too bad... this is debug !!) - io_seproxyhal_spi_recv(G_io_seproxyhal_spi_buffer, sizeof(G_io_seproxyhal_spi_buffer), 0); + BAGL_FONT_OPEN_SANS_EXTRABOLD_11px | BAGL_FONT_ALIGNMENT_CENTER | BAGL_FONT_ALIGNMENT_MIDDLE +#else // TARGET_NANOS + BAGL_FONT_OPEN_SANS_REGULAR_8_11PX +#endif // TARGET_NANOS + , + 0}, + .text = "Default printf" +}; + +void debug_wait_displayed(void) +{ + // wait next event (probably a ticker, if not, too bad... this is debug !!) + io_seproxyhal_spi_recv(G_io_seproxyhal_spi_buffer, sizeof(G_io_seproxyhal_spi_buffer), 0); } #if defined(HAVE_DEBUG) || defined(BOLOS_DEBUG) #include "string.h" -void debug_printf(void* buffer) { +void debug_printf(void *buffer) +{ #ifdef TARGET_NANOS - io_seproxyhal_display_default(&clear_element); - debug_wait_displayed(); -#endif // TARGET_NANOS - memmove(&G_ux.tmp_element, &printf_element, sizeof(bagl_element_t)); - G_ux.tmp_element.text = buffer; - io_seproxyhal_display_default(&G_ux.tmp_element); - debug_wait_displayed(); - // // ask to replicate mcu buffer to the screen - // io_seproxyhal_general_status(); - // // wait up the display processed - // io_seproxyhal_spi_recv(G_io_seproxyhal_spi_buffer, sizeof(G_io_seproxyhal_spi_buffer), 0); - // wait until a button event - while (G_io_seproxyhal_spi_buffer[0] != SEPROXYHAL_TAG_BUTTON_PUSH_EVENT - // not marked as released - || G_io_seproxyhal_spi_buffer[3] != 0) { - io_seproxyhal_general_status(); - io_seproxyhal_spi_recv(G_io_seproxyhal_spi_buffer, sizeof(G_io_seproxyhal_spi_buffer), 0); - } + io_seproxyhal_display_default(&clear_element); + debug_wait_displayed(); +#endif // TARGET_NANOS + memmove(&G_ux.tmp_element, &printf_element, sizeof(bagl_element_t)); + G_ux.tmp_element.text = buffer; + io_seproxyhal_display_default(&G_ux.tmp_element); + debug_wait_displayed(); + // // ask to replicate mcu buffer to the screen + // io_seproxyhal_general_status(); + // // wait up the display processed + // io_seproxyhal_spi_recv(G_io_seproxyhal_spi_buffer, sizeof(G_io_seproxyhal_spi_buffer), 0); + // wait until a button event + while (G_io_seproxyhal_spi_buffer[0] != SEPROXYHAL_TAG_BUTTON_PUSH_EVENT + // not marked as released + || G_io_seproxyhal_spi_buffer[3] != 0) { + io_seproxyhal_general_status(); + io_seproxyhal_spi_recv(G_io_seproxyhal_spi_buffer, sizeof(G_io_seproxyhal_spi_buffer), 0); + } } -#endif // defined(HAVE_DEBUG) || defined(BOLOS_DEBUG) +#endif // defined(HAVE_DEBUG) || defined(BOLOS_DEBUG) #ifdef HAVE_DEBUG #define L(x) debug_printf(x) -#else // HAVE_DEBUG +#else // HAVE_DEBUG #define L(x) -#endif // HAVE_DEBUG - +#endif // HAVE_DEBUG // void ux_check_status_default(unsigned int status) { // // nothing to be done here by default. // UNUSED(status); // } -// void ux_check_status(unsigned int status) __attribute__ ((weak, alias ("ux_check_status_default"))); +// void ux_check_status(unsigned int status) __attribute__ ((weak, alias +// ("ux_check_status_default"))); diff --git a/lib_ux/src/ux_menulist.c b/lib_ux/src/ux_menulist.c index b983862c5..e49e6b6dd 100644 --- a/lib_ux/src/ux_menulist.c +++ b/lib_ux/src/ux_menulist.c @@ -1,20 +1,20 @@ /******************************************************************************* -* Ledger Nano S - Secure firmware -* (c) 2022 Ledger -* -* Licensed under the Apache License, Version 2.0 (the "License"); -* you may not use this file except in compliance with the License. -* You may obtain a copy of the License at -* -* http://www.apache.org/licenses/LICENSE-2.0 -* -* Unless required by applicable law or agreed to in writing, software -* distributed under the License is distributed on an "AS IS" BASIS, -* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -* See the License for the specific language governing permissions and -* limitations under the License. -********************************************************************************/ + * Ledger Nano S - Secure firmware + * (c) 2022 Ledger + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT 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 "ux.h" #include "os_helpers.h" @@ -23,75 +23,72 @@ void ux_menulist_refresh(unsigned int stack_slot); -unsigned int ux_menulist_button(unsigned int button_mask, unsigned int button_mask_counter) { - UNUSED(button_mask_counter); +unsigned int ux_menulist_button(unsigned int button_mask, unsigned int button_mask_counter) +{ + UNUSED(button_mask_counter); - switch(button_mask) { - case BUTTON_EVT_RELEASED|BUTTON_LEFT: - if (G_ux.menulist_getter(G_ux.menulist_current-1UL)) { - G_ux.menulist_current--; - ux_menulist_refresh(G_ux.stack_count-1); - } - break; - case BUTTON_EVT_RELEASED|BUTTON_RIGHT: - if (G_ux.menulist_getter(G_ux.menulist_current+1UL)) { - G_ux.menulist_current++; - ux_menulist_refresh(G_ux.stack_count-1); - } - break; - case BUTTON_EVT_RELEASED|BUTTON_LEFT|BUTTON_RIGHT: - G_ux.menulist_selector(G_ux.menulist_current); - break; - } - return 0; + switch (button_mask) { + case BUTTON_EVT_RELEASED | BUTTON_LEFT: + if (G_ux.menulist_getter(G_ux.menulist_current - 1UL)) { + G_ux.menulist_current--; + ux_menulist_refresh(G_ux.stack_count - 1); + } + break; + case BUTTON_EVT_RELEASED | BUTTON_RIGHT: + if (G_ux.menulist_getter(G_ux.menulist_current + 1UL)) { + G_ux.menulist_current++; + ux_menulist_refresh(G_ux.stack_count - 1); + } + break; + case BUTTON_EVT_RELEASED | BUTTON_LEFT | BUTTON_RIGHT: + G_ux.menulist_selector(G_ux.menulist_current); + break; + } + return 0; } -void ux_menulist_refresh(unsigned int stack_slot) { - // set values - int i; - for (i = 0; i < 5; i++) { - G_ux.menulist_params.lines[i] = G_ux.menulist_getter(G_ux.menulist_current+i-2); - } - // display (strings are localized before being displayed) - ux_layout_nnbnn_init(stack_slot); - // change callback to the menulist one - G_ux.stack[stack_slot].button_push_callback = ux_menulist_button; +void ux_menulist_refresh(unsigned int stack_slot) +{ + // set values + int i; + for (i = 0; i < 5; i++) { + G_ux.menulist_params.lines[i] = G_ux.menulist_getter(G_ux.menulist_current + i - 2); + } + // display (strings are localized before being displayed) + ux_layout_nnbnn_init(stack_slot); + // change callback to the menulist one + G_ux.stack[stack_slot].button_push_callback = ux_menulist_button; } -const ux_flow_step_t ux_menulist_conststep = { - ux_menulist_refresh, - &G_ux.menulist_params, - NULL, - NULL -}; -UX_FLOW( - ux_menulist_constflow, - &ux_menulist_conststep - ); +const ux_flow_step_t ux_menulist_conststep + = {ux_menulist_refresh, &G_ux.menulist_params, NULL, NULL}; +UX_FLOW(ux_menulist_constflow, &ux_menulist_conststep); -void ux_menulist_init_select(unsigned int stack_slot, - list_item_value_t getter, - list_item_select_t selector, - unsigned int selected_item_idx) { - G_ux.menulist_current = selected_item_idx; - G_ux.menulist_getter = getter; - G_ux.menulist_selector = selector; +void ux_menulist_init_select(unsigned int stack_slot, + list_item_value_t getter, + list_item_select_t selector, + unsigned int selected_item_idx) +{ + G_ux.menulist_current = selected_item_idx; + G_ux.menulist_getter = getter; + G_ux.menulist_selector = selector; - // ensure the current flow step reference the G_ux.menulist_params to ensure strings displayed correctly. - // if not, then use the forged step (and display it if top of ux stack) - if (ux_stack_get_step_params(stack_slot) != (void*)&G_ux.menulist_params) { - ux_flow_init(stack_slot, ux_menulist_constflow, NULL); - } - else { - ux_menulist_refresh(stack_slot); - } + // ensure the current flow step reference the G_ux.menulist_params to ensure strings displayed + // correctly. if not, then use the forged step (and display it if top of ux stack) + if (ux_stack_get_step_params(stack_slot) != (void *) &G_ux.menulist_params) { + ux_flow_init(stack_slot, ux_menulist_constflow, NULL); + } + else { + ux_menulist_refresh(stack_slot); + } } // based on a nnbnn layout -void ux_menulist_init(unsigned int stack_slot, - list_item_value_t getter, - list_item_select_t selector) { - ux_menulist_init_select(stack_slot, getter, selector, 0); +void ux_menulist_init(unsigned int stack_slot, + list_item_value_t getter, + list_item_select_t selector) +{ + ux_menulist_init_select(stack_slot, getter, selector, 0); } -#endif // HAVE_UX_FLOW +#endif // HAVE_UX_FLOW diff --git a/lib_ux/src/ux_stack.c b/lib_ux/src/ux_stack.c index a3c7e71fc..69f0bd52f 100644 --- a/lib_ux/src/ux_stack.c +++ b/lib_ux/src/ux_stack.c @@ -1,20 +1,20 @@ /******************************************************************************* -* Ledger Nano S - Secure firmware -* (c) 2022 Ledger -* -* Licensed under the Apache License, Version 2.0 (the "License"); -* you may not use this file except in compliance with the License. -* You may obtain a copy of the License at -* -* http://www.apache.org/licenses/LICENSE-2.0 -* -* Unless required by applicable law or agreed to in writing, software -* distributed under the License is distributed on an "AS IS" BASIS, -* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -* See the License for the specific language governing permissions and -* limitations under the License. -********************************************************************************/ + * Ledger Nano S - Secure firmware + * (c) 2022 Ledger + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT 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 "ux.h" #include "os_pin.h" @@ -26,299 +26,328 @@ #include // return true (stack slot +1) if an element -unsigned int ux_stack_is_element_array_present(const bagl_element_t *element_array) { - unsigned int i, j; +unsigned int ux_stack_is_element_array_present(const bagl_element_t *element_array) +{ + unsigned int i, j; - // looks for a element array though the ux stack - for (i = 0; i < ARRAYLEN(G_ux.stack) && i < G_ux.stack_count; i++) { - for (j = 0; j < UX_STACK_SLOT_ARRAY_COUNT && j < G_ux.stack[i].element_arrays_count; j++) { - if (G_ux.stack[i].element_arrays[j].element_array == element_array) { - return i + 1; - } + // looks for a element array though the ux stack + for (i = 0; i < ARRAYLEN(G_ux.stack) && i < G_ux.stack_count; i++) { + for (j = 0; j < UX_STACK_SLOT_ARRAY_COUNT && j < G_ux.stack[i].element_arrays_count; j++) { + if (G_ux.stack[i].element_arrays[j].element_array == element_array) { + return i + 1; + } + } } - } - return 0; + return 0; } -unsigned int ux_stack_push(void) { - // only push if an available slot exists - if (G_ux.stack_count < ARRAYLEN(G_ux.stack)) { - memset(&G_ux.stack[G_ux.stack_count], 0, sizeof(G_ux.stack[0])); +unsigned int ux_stack_push(void) +{ + // only push if an available slot exists + if (G_ux.stack_count < ARRAYLEN(G_ux.stack)) { + memset(&G_ux.stack[G_ux.stack_count], 0, sizeof(G_ux.stack[0])); #ifdef HAVE_UX_FLOW - memset(&G_ux.flow_stack[G_ux.stack_count], 0, sizeof(G_ux.flow_stack[0])); -#endif // HAVE_UX_FLOW - G_ux.stack_count++; - } - // return the stack top index - return G_ux.stack_count - 1; + memset(&G_ux.flow_stack[G_ux.stack_count], 0, sizeof(G_ux.flow_stack[0])); +#endif // HAVE_UX_FLOW + G_ux.stack_count++; + } + // return the stack top index + return G_ux.stack_count - 1; } -unsigned int ux_stack_pop(void) { - unsigned int exit_code = BOLOS_UX_OK; - // only pop if more than two stack entry (0 and 1,top is an index not a count) - if (G_ux.stack_count > 0) { - G_ux.stack_count--; - if (G_ux.stack_count < UX_STACK_SLOT_COUNT) { - exit_code = G_ux.stack[G_ux.stack_count].exit_code_after_elements_displayed; - // wipe popped slot - memset(&G_ux.stack[G_ux.stack_count], 0, sizeof(G_ux.stack[0])); +unsigned int ux_stack_pop(void) +{ + unsigned int exit_code = BOLOS_UX_OK; + // only pop if more than two stack entry (0 and 1,top is an index not a count) + if (G_ux.stack_count > 0) { + G_ux.stack_count--; + if (G_ux.stack_count < UX_STACK_SLOT_COUNT) { + exit_code = G_ux.stack[G_ux.stack_count].exit_code_after_elements_displayed; + // wipe popped slot + memset(&G_ux.stack[G_ux.stack_count], 0, sizeof(G_ux.stack[0])); #ifdef HAVE_UX_FLOW - memset(&G_ux.flow_stack[G_ux.stack_count], 0, sizeof(G_ux.flow_stack[0])); -#endif // HAVE_UX_FLOW + memset(&G_ux.flow_stack[G_ux.stack_count], 0, sizeof(G_ux.flow_stack[0])); +#endif // HAVE_UX_FLOW + } } - } - // prepare output code when popping the last stack screen - if (G_ux.stack_count == 0) { - G_ux.exit_code = exit_code; - } - // ask for a complete redraw (optimisation due to blink must be avoided as we're returning from a modal, and within - // the bolos ux screen stack) - else { - // prepare to redraw the slot when asked - G_ux.stack[G_ux.stack_count - 1].element_index = 0; - } - // return the stack top index (or -1 if no top) - return G_ux.stack_count - 1; + // prepare output code when popping the last stack screen + if (G_ux.stack_count == 0) { + G_ux.exit_code = exit_code; + } + // ask for a complete redraw (optimisation due to blink must be avoided as we're returning from + // a modal, and within the bolos ux screen stack) + else { + // prepare to redraw the slot when asked + G_ux.stack[G_ux.stack_count - 1].element_index = 0; + } + // return the stack top index (or -1 if no top) + return G_ux.stack_count - 1; } -void ux_stack_redisplay(void) { +void ux_stack_redisplay(void) +{ #ifdef HAVE_UX_FLOW - // an ux step has been relayout on the screen, don't flicker by redisplaying here - if (ux_flow_relayout()) { - return; - } -#endif // HAVE_UX_FLOW + // an ux step has been relayout on the screen, don't flicker by redisplaying here + if (ux_flow_relayout()) { + return; + } +#endif // HAVE_UX_FLOW - // check if any screen is schedule for displaying - if (G_ux.stack_count > 0 && G_ux.stack_count <= ARRAYLEN(G_ux.stack)) { - G_ux.stack[G_ux.stack_count - 1].element_index = 0; - ux_stack_display(G_ux.stack_count - 1); - } - // else return redraw for the app - else if (G_ux.stack_count == 0) { - if (G_ux.exit_code == BOLOS_UX_OK) { - G_ux.exit_code = BOLOS_UX_REDRAW; + // check if any screen is schedule for displaying + if (G_ux.stack_count > 0 && G_ux.stack_count <= ARRAYLEN(G_ux.stack)) { + G_ux.stack[G_ux.stack_count - 1].element_index = 0; + ux_stack_display(G_ux.stack_count - 1); + } + // else return redraw for the app + else if (G_ux.stack_count == 0) { + if (G_ux.exit_code == BOLOS_UX_OK) { + G_ux.exit_code = BOLOS_UX_REDRAW; + } } - } } -void ux_stack_insert(unsigned int stack_slot) { - if (stack_slot >= ARRAYLEN(G_ux.stack)) { - return; // arbitrary, this is feil that's it - } - // not a full stack - if (G_ux.stack_count < ARRAYLEN(G_ux.stack)) { - // if not inserting as top of stack, then perform move - if (stack_slot != ARRAYLEN(G_ux.stack) - 1) { - memmove(&G_ux.stack[stack_slot + 1], &G_ux.stack[stack_slot], - (ARRAYLEN(G_ux.stack) - (stack_slot + 1)) * sizeof(G_ux.stack[0])); -#ifdef HAVE_UX_FLOW - memmove(&G_ux.flow_stack[stack_slot + 1], &G_ux.flow_stack[stack_slot], - (ARRAYLEN(G_ux.flow_stack) - (stack_slot + 1)) * sizeof(G_ux.flow_stack[0])); -#endif // HAVE_UX_FLOW +void ux_stack_insert(unsigned int stack_slot) +{ + if (stack_slot >= ARRAYLEN(G_ux.stack)) { + return; // arbitrary, this is feil that's it } - memset(&G_ux.stack[stack_slot], 0, sizeof(ux_stack_slot_t)); + // not a full stack + if (G_ux.stack_count < ARRAYLEN(G_ux.stack)) { + // if not inserting as top of stack, then perform move + if (stack_slot != ARRAYLEN(G_ux.stack) - 1) { + memmove(&G_ux.stack[stack_slot + 1], + &G_ux.stack[stack_slot], + (ARRAYLEN(G_ux.stack) - (stack_slot + 1)) * sizeof(G_ux.stack[0])); +#ifdef HAVE_UX_FLOW + memmove(&G_ux.flow_stack[stack_slot + 1], + &G_ux.flow_stack[stack_slot], + (ARRAYLEN(G_ux.flow_stack) - (stack_slot + 1)) * sizeof(G_ux.flow_stack[0])); +#endif // HAVE_UX_FLOW + } + memset(&G_ux.stack[stack_slot], 0, sizeof(ux_stack_slot_t)); #ifdef HAVE_UX_FLOW - memset(&G_ux.flow_stack[stack_slot], 0, sizeof(ux_flow_state_t)); -#endif // HAVE_UX_FLOW - // add the slot - G_ux.stack_count++; - // slot not wiped - } - // feil, that's it + memset(&G_ux.flow_stack[stack_slot], 0, sizeof(ux_flow_state_t)); +#endif // HAVE_UX_FLOW + // add the slot + G_ux.stack_count++; + // slot not wiped + } + // feil, that's it } -void ux_stack_remove(unsigned int stack_slot) { - if (stack_slot > ARRAYLEN(G_ux.stack) - 1) { - stack_slot = ARRAYLEN(G_ux.stack) - 1; - } +void ux_stack_remove(unsigned int stack_slot) +{ + if (stack_slot > ARRAYLEN(G_ux.stack) - 1) { + stack_slot = ARRAYLEN(G_ux.stack) - 1; + } - // removing something not in stack - if (stack_slot >= G_ux.stack_count) { - return; - } + // removing something not in stack + if (stack_slot >= G_ux.stack_count) { + return; + } - // before: | screenz | removed screen | other screenz | - // after: | screenz | other screenz | + // before: | screenz | removed screen | other screenz | + // after: | screenz | other screenz | - if (stack_slot != ARRAYLEN(G_ux.stack) - 1) { - memmove(&G_ux.stack[stack_slot], &G_ux.stack[stack_slot + 1], - (ARRAYLEN(G_ux.stack) - (stack_slot + 1)) * sizeof(G_ux.stack[0])); + if (stack_slot != ARRAYLEN(G_ux.stack) - 1) { + memmove(&G_ux.stack[stack_slot], + &G_ux.stack[stack_slot + 1], + (ARRAYLEN(G_ux.stack) - (stack_slot + 1)) * sizeof(G_ux.stack[0])); #ifdef HAVE_UX_FLOW - // also move the flow attached to the popped screen - memmove(&G_ux.flow_stack[stack_slot], &G_ux.flow_stack[stack_slot + 1], - (ARRAYLEN(G_ux.flow_stack) - (stack_slot + 1)) * sizeof(G_ux.flow_stack[0])); -#endif // HAVE_UX_FLOW - } + // also move the flow attached to the popped screen + memmove(&G_ux.flow_stack[stack_slot], + &G_ux.flow_stack[stack_slot + 1], + (ARRAYLEN(G_ux.flow_stack) - (stack_slot + 1)) * sizeof(G_ux.flow_stack[0])); +#endif // HAVE_UX_FLOW + } - // wipe last slot - ux_stack_pop(); + // wipe last slot + ux_stack_pop(); } // common code for all screens -void ux_stack_init(unsigned int stack_slot) { - // reinit ux behavior (previous touched element, button push state) - io_seproxyhal_init_ux(); // glitch upon ux_stack_display for a button being pressed in a previous screen +void ux_stack_init(unsigned int stack_slot) +{ + // reinit ux behavior (previous touched element, button push state) + io_seproxyhal_init_ux(); // glitch upon ux_stack_display for a button being pressed in a + // previous screen - /* - // mismatch, the stack slot is not accessible !! - if (G_ux.stack_countelement_arrays_count; i++) { - // compute elem_idx in the current array (element_index refers to the total number of element to display) - elem_idx = slot->element_index - total_element_count; - total_element_count += slot->element_arrays[i].element_array_count; - // check if we're sending from this array or not - while (elem_idx < slot->element_arrays[i].element_array_count) { - const bagl_element_t *el; - // pre inc before callback to allow callback to change the next element to be drawn - slot->element_index++; + if ((os_perso_isonboarded() != BOLOS_UX_OK || os_global_pin_is_validated() == BOLOS_UX_OK)) +#endif // HAVE_BOLOS + { + for (i = 0; i < UX_STACK_SLOT_ARRAY_COUNT && i < slot->element_arrays_count; i++) { + // compute elem_idx in the current array (element_index refers to the total number of + // element to display) + elem_idx = slot->element_index - total_element_count; + total_element_count += slot->element_arrays[i].element_array_count; + // check if we're sending from this array or not + while (elem_idx < slot->element_arrays[i].element_array_count) { + const bagl_element_t *el; + // pre inc before callback to allow callback to change the next element to be drawn + slot->element_index++; - element = &slot->element_arrays[i].element_array[elem_idx]; - el = ux_stack_display_element_callback(element); - if (!el) { - // skip display if requested to - if ( - //! io_seproxyhal_spi_is_status_sent() && - G_ux.exit_code != BOLOS_UX_CONTINUE) { - return; - } - } else { - // legacy support - if ((unsigned int)el != 1) { - element = el; - } - io_seproxyhal_display(element); + element = &slot->element_arrays[i].element_array[elem_idx]; + el = ux_stack_display_element_callback(element); + if (!el) { + // skip display if requested to + if ( + //! io_seproxyhal_spi_is_status_sent() && + G_ux.exit_code != BOLOS_UX_CONTINUE) { + return; + } + } + else { + // legacy support + if ((unsigned int) el != 1) { + element = el; + } + io_seproxyhal_display(element); + } + elem_idx++; + } } - elem_idx++; - } - } - // TODO draw the status bar + // TODO draw the status bar - if (slot->element_index == total_element_count) { - // if screen has special stuff todo on exit - screen_update(); - // screen marked as displayed - slot->element_index++; + if (slot->element_index == total_element_count) { + // if screen has special stuff todo on exit + screen_update(); + // screen marked as displayed + slot->element_index++; - // check if a displayed callback is requiring redraw - if (slot->displayed_callback) { - // if screen displayed callback requested one more round, then set CONTINUE exit code - if (!slot->displayed_callback(0)) { - slot->element_index = 0; - G_ux.exit_code = BOLOS_UX_CONTINUE; - return; // break; + // check if a displayed callback is requiring redraw + if (slot->displayed_callback) { + // if screen displayed callback requested one more round, then set CONTINUE exit + // code + if (!slot->displayed_callback(0)) { + slot->element_index = 0; + G_ux.exit_code = BOLOS_UX_CONTINUE; + return; // break; + } + } + G_ux.exit_code = slot->exit_code_after_elements_displayed; } - } - G_ux.exit_code = slot->exit_code_after_elements_displayed; } - } } -#endif // HAVE_SE_SCREEN +#endif // HAVE_SE_SCREEN #ifndef HAVE_SE_SCREEN void ux_stack_al_display_next_element(unsigned int stack_slot) __attribute__((weak)); -void ux_stack_al_display_next_element(unsigned int stack_slot) { +void ux_stack_al_display_next_element(unsigned int stack_slot) +{ #if UX_STACK_SLOT_ARRAY_COUNT == 1 - unsigned int status = os_sched_last_status(TASK_BOLOS_UX); - if (status != BOLOS_UX_IGNORE && status != BOLOS_UX_CONTINUE) { - while (G_ux.stack[stack_slot].element_arrays[0].element_array && - G_ux.stack[stack_slot].element_index < G_ux.stack[stack_slot].element_arrays[0].element_array_count && - !io_seproxyhal_spi_is_status_sent() && - (os_perso_isonboarded() != BOLOS_UX_OK || os_global_pin_is_validated() == BOLOS_UX_OK)) { - const bagl_element_t *element = - &G_ux.stack[stack_slot].element_arrays[0].element_array[G_ux.stack[stack_slot].element_index]; - if (!G_ux.stack[stack_slot].screen_before_element_display_callback || - (element = G_ux.stack[stack_slot].screen_before_element_display_callback(element))) { - if ((unsigned int)element == 1) { /*backward compat with coding to avoid smashing everything*/ - element = &G_ux.stack[stack_slot].element_arrays[0].element_array[G_ux.stack[stack_slot].element_index]; + unsigned int status = os_sched_last_status(TASK_BOLOS_UX); + if (status != BOLOS_UX_IGNORE && status != BOLOS_UX_CONTINUE) { + while (G_ux.stack[stack_slot].element_arrays[0].element_array + && G_ux.stack[stack_slot].element_index + < G_ux.stack[stack_slot].element_arrays[0].element_array_count + && !io_seproxyhal_spi_is_status_sent() + && (os_perso_isonboarded() != BOLOS_UX_OK + || os_global_pin_is_validated() == BOLOS_UX_OK)) { + const bagl_element_t *element + = &G_ux.stack[stack_slot] + .element_arrays[0] + .element_array[G_ux.stack[stack_slot].element_index]; + if (!G_ux.stack[stack_slot].screen_before_element_display_callback + || (element + = G_ux.stack[stack_slot].screen_before_element_display_callback(element))) { + if ((unsigned int) element + == 1) { /*backward compat with coding to avoid smashing everything*/ + element = &G_ux.stack[stack_slot] + .element_arrays[0] + .element_array[G_ux.stack[stack_slot].element_index]; + } + io_seproxyhal_display(element); + } + G_ux.stack[stack_slot].element_index++; } - io_seproxyhal_display(element); - } - G_ux.stack[stack_slot].element_index++; } - } -#endif // UX_STACK_SLOT_ARRAY_COUNT == 1 +#endif // UX_STACK_SLOT_ARRAY_COUNT == 1 } -#endif // HAVE_SE_SCREEN +#endif // HAVE_SE_SCREEN // common code for all screens -void ux_stack_display(unsigned int stack_slot) { - // don't display any elements of a previous screen replacement - if (G_ux.stack_count > 0 && stack_slot + 1 == G_ux.stack_count) { - io_seproxyhal_init_ux(); - // at worse a redisplay of the current screen has been requested, ensure to redraw it correctly - G_ux.stack[stack_slot].element_index = 0; +void ux_stack_display(unsigned int stack_slot) +{ + // don't display any elements of a previous screen replacement + if (G_ux.stack_count > 0 && stack_slot + 1 == G_ux.stack_count) { + io_seproxyhal_init_ux(); + // at worse a redisplay of the current screen has been requested, ensure to redraw it + // correctly + G_ux.stack[stack_slot].element_index = 0; #ifdef HAVE_SE_SCREEN - ux_stack_display_elements(&G_ux.stack[stack_slot]); // on balenos, no need to wait for the display processed event -#else // HAVE_SE_SCREEN - ux_stack_al_display_next_element(stack_slot); -#endif // HAVE_SE_SCREEN - } - // asking to redraw below top screen (likely the app below the ux) - else if (stack_slot == -1UL || G_ux.stack_count == 0) { - if (G_ux.exit_code == BOLOS_UX_OK) { - G_ux.exit_code = BOLOS_UX_REDRAW; + ux_stack_display_elements(&G_ux.stack[stack_slot]); // on balenos, no need to wait for the + // display processed event +#else // HAVE_SE_SCREEN + ux_stack_al_display_next_element(stack_slot); +#endif // HAVE_SE_SCREEN + } + // asking to redraw below top screen (likely the app below the ux) + else if (stack_slot == -1UL || G_ux.stack_count == 0) { + if (G_ux.exit_code == BOLOS_UX_OK) { + G_ux.exit_code = BOLOS_UX_REDRAW; + } } - } - // else don't draw (in stack insertion) + // else don't draw (in stack insertion) } diff --git a/lib_ux_stax/ux.c b/lib_ux_stax/ux.c index 349f43db3..8ac3b24c1 100644 --- a/lib_ux_stax/ux.c +++ b/lib_ux_stax/ux.c @@ -1,20 +1,20 @@ /******************************************************************************* -* Ledger Nano S - Secure firmware -* (c) 2022 Ledger -* -* Licensed under the Apache License, Version 2.0 (the "License"); -* you may not use this file except in compliance with the License. -* You may obtain a copy of the License at -* -* http://www.apache.org/licenses/LICENSE-2.0 -* -* Unless required by applicable law or agreed to in writing, software -* distributed under the License is distributed on an "AS IS" BASIS, -* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -* See the License for the specific language governing permissions and -* limitations under the License. -********************************************************************************/ + * Ledger Nano S - Secure firmware + * (c) 2022 Ledger + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT 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 "seproxyhal_protocol.h" #include "ux.h" @@ -25,43 +25,46 @@ static uint32_t nbTicks; /** - * @brief internal bolos ux event processing with callback in case event is to be processed by the application + * @brief internal bolos ux event processing with callback in case event is to be processed by the + * application * * @param ignoring_app_if_ux_busy if set to false, function returns true if no REDRAW needed * @return true if ignoring_app_if_ux_busy is false or UX is not busy */ -static bool ux_forward_event(bool ignoring_app_if_ux_busy) { - G_ux_params.ux_id = BOLOS_UX_EVENT; - G_ux_params.len = 0; - os_ux(&G_ux_params); - G_ux_params.len = os_sched_last_status(TASK_BOLOS_UX); +static bool ux_forward_event(bool ignoring_app_if_ux_busy) +{ + G_ux_params.ux_id = BOLOS_UX_EVENT; + G_ux_params.len = 0; + os_ux(&G_ux_params); + G_ux_params.len = os_sched_last_status(TASK_BOLOS_UX); #ifdef HAVE_BLE - if (G_ux.asynchmodal_end_callback && - (os_ux_get_status(BOLOS_UX_ASYNCHMODAL_PAIRING_REQUEST) != 0)) { - asynchmodal_end_callback_t cb = G_ux.asynchmodal_end_callback; - // reset G_ux.asynchmodal_end_callback for next time - G_ux.asynchmodal_end_callback = NULL; - cb(os_ux_get_status(BOLOS_UX_ASYNCHMODAL_PAIRING_REQUEST)); - // for app to redraw/refresh itself - G_ux_params.len = BOLOS_UX_REDRAW; - } -#endif // HAVE_BLE - if (G_ux_params.len == BOLOS_UX_REDRAW) { - // enable drawing according to UX decision - nbgl_objAllowDrawing(true); - nbgl_screenRedraw(); - nbgl_refresh(); - } - else if (!ignoring_app_if_ux_busy || - ((G_ux_params.len != BOLOS_UX_IGNORE) && (G_ux_params.len != BOLOS_UX_CONTINUE))) { - return true; - } - return false; + if (G_ux.asynchmodal_end_callback + && (os_ux_get_status(BOLOS_UX_ASYNCHMODAL_PAIRING_REQUEST) != 0)) { + asynchmodal_end_callback_t cb = G_ux.asynchmodal_end_callback; + // reset G_ux.asynchmodal_end_callback for next time + G_ux.asynchmodal_end_callback = NULL; + cb(os_ux_get_status(BOLOS_UX_ASYNCHMODAL_PAIRING_REQUEST)); + // for app to redraw/refresh itself + G_ux_params.len = BOLOS_UX_REDRAW; + } +#endif // HAVE_BLE + if (G_ux_params.len == BOLOS_UX_REDRAW) { + // enable drawing according to UX decision + nbgl_objAllowDrawing(true); + nbgl_screenRedraw(); + nbgl_refresh(); + } + else if (!ignoring_app_if_ux_busy + || ((G_ux_params.len != BOLOS_UX_IGNORE) && (G_ux_params.len != BOLOS_UX_CONTINUE))) { + return true; + } + return false; } /** * @brief Process finger event. - * @note Application's finger event handler is called only if the ux app does not deny it (finger event caught by BOLOS UX page). + * @note Application's finger event handler is called only if the ux app does not deny it (finger + * event caught by BOLOS UX page). * * @param seph_packet received SEPH packet * @param nbTicks number of 100ms ticks from the launch of the app @@ -69,58 +72,62 @@ static bool ux_forward_event(bool ignoring_app_if_ux_busy) { static nbgl_touchStatePosition_t pos; -void ux_process_finger_event(uint8_t seph_packet[]) { - bool displayEnabled = ux_forward_event(true); - // enable/disable drawing according to UX decision - nbgl_objAllowDrawing(displayEnabled); +void ux_process_finger_event(uint8_t seph_packet[]) +{ + bool displayEnabled = ux_forward_event(true); + // enable/disable drawing according to UX decision + nbgl_objAllowDrawing(displayEnabled); - // if the event is not fully consumed by UX, use it for NBGL - if (displayEnabled) { - pos.state = (seph_packet[3] == SEPROXYHAL_TAG_FINGER_EVENT_TOUCH) ? PRESSED : RELEASED; - pos.x = (seph_packet[4] << 8) + seph_packet[5]; - pos.y = (seph_packet[6] << 8) + seph_packet[7]; - nbgl_touchHandler(&pos, nbTicks * 100); - nbgl_refresh(); - } + // if the event is not fully consumed by UX, use it for NBGL + if (displayEnabled) { + pos.state = (seph_packet[3] == SEPROXYHAL_TAG_FINGER_EVENT_TOUCH) ? PRESSED : RELEASED; + pos.x = (seph_packet[4] << 8) + seph_packet[5]; + pos.y = (seph_packet[6] << 8) + seph_packet[7]; + nbgl_touchHandler(&pos, nbTicks * 100); + nbgl_refresh(); + } } /** - * @brief Process the ticker_event to the os ux handler. Ticker event callback is always called whatever the return code of the ux app. + * @brief Process the ticker_event to the os ux handler. Ticker event callback is always called + * whatever the return code of the ux app. * @note Ticker event interval is assumed to be 100 ms. */ -void ux_process_ticker_event(void) { - nbTicks++; - // forward to UX - bool displayEnabled = ux_forward_event(true); +void ux_process_ticker_event(void) +{ + nbTicks++; + // forward to UX + bool displayEnabled = ux_forward_event(true); - // enable/disable drawing according to UX decision - nbgl_objAllowDrawing(displayEnabled); - // update ticker in NBGL - nbgl_screenHandler(100); + // enable/disable drawing according to UX decision + nbgl_objAllowDrawing(displayEnabled); + // update ticker in NBGL + nbgl_screenHandler(100); - if (!displayEnabled) { - return; - } + if (!displayEnabled) { + return; + } - // handle touch only if detected as pressed in last touch message - if (pos.state == PRESSED) { - io_touch_info_t touch_info; - touch_get_last_info(&touch_info); - pos.state = (touch_info.state == SEPROXYHAL_TAG_FINGER_EVENT_TOUCH)? PRESSED : RELEASED; - pos.x = touch_info.x; - pos.y = touch_info.y; - // Send current touch position to nbgl - nbgl_touchHandler(&pos, nbTicks * 100); - } - nbgl_refresh(); + // handle touch only if detected as pressed in last touch message + if (pos.state == PRESSED) { + io_touch_info_t touch_info; + touch_get_last_info(&touch_info); + pos.state = (touch_info.state == SEPROXYHAL_TAG_FINGER_EVENT_TOUCH) ? PRESSED : RELEASED; + pos.x = touch_info.x; + pos.y = touch_info.y; + // Send current touch position to nbgl + nbgl_touchHandler(&pos, nbTicks * 100); + } + nbgl_refresh(); } /** * Forwards the event to UX */ -void ux_process_default_event(void) { - // forward to UX - ux_forward_event(false); +void ux_process_default_event(void) +{ + // forward to UX + ux_forward_event(false); } -#endif // HAVE_BOLOS +#endif // HAVE_BOLOS diff --git a/lib_ux_stax/ux.h b/lib_ux_stax/ux.h index a98fba671..26b153e4d 100644 --- a/lib_ux_stax/ux.h +++ b/lib_ux_stax/ux.h @@ -1,20 +1,20 @@ /******************************************************************************* -* Ledger Nano S - Secure firmware -* (c) 2022 Ledger -* -* Licensed under the Apache License, Version 2.0 (the "License"); -* you may not use this file except in compliance with the License. -* You may obtain a copy of the License at -* -* http://www.apache.org/licenses/LICENSE-2.0 -* -* Unless required by applicable law or agreed to in writing, software -* distributed under the License is distributed on an "AS IS" BASIS, -* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -* See the License for the specific language governing permissions and -* limitations under the License. -********************************************************************************/ + * Ledger Nano S - Secure firmware + * (c) 2022 Ledger + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + ********************************************************************************/ #pragma once @@ -26,8 +26,7 @@ #include - -typedef void (*asynchmodal_end_callback_t) (unsigned int ux_status); +typedef void (*asynchmodal_end_callback_t)(unsigned int ux_status); /** * Common structure for applications to perform asynchronous UX aside IO operations @@ -35,15 +34,15 @@ typedef void (*asynchmodal_end_callback_t) (unsigned int ux_s typedef struct ux_state_s ux_state_t; struct ux_state_s { - bolos_task_status_t exit_code; - bool validate_pin_from_dashboard; // set to true when BOLOS_UX_VALIDATE_PIN is received from Dashboard task + bolos_task_status_t exit_code; + bool validate_pin_from_dashboard; // set to true when BOLOS_UX_VALIDATE_PIN is received from + // Dashboard task - asynchmodal_end_callback_t asynchmodal_end_callback; + asynchmodal_end_callback_t asynchmodal_end_callback; - char string_buffer[128]; + char string_buffer[128]; }; - extern ux_state_t G_ux; #if !defined(APP_UX) extern bolos_ux_params_t G_ux_params; @@ -51,41 +50,45 @@ extern bolos_ux_params_t G_ux_params; extern void ux_process_finger_event(uint8_t seph_packet[]); extern void ux_process_ticker_event(void); extern void ux_process_default_event(void); -#endif // !defined(APP_UX) +#endif // !defined(APP_UX) /** * Initialize the user experience structure */ -#define UX_INIT() \ - nbgl_objInit(); - +#define UX_INIT() nbgl_objInit(); #ifdef HAVE_BOLOS // to be used only by hal_io.c in BOLOS, for compatibility -#define UX_FORWARD_EVENT_REDRAWCB(bypasspincheck, ux_params, ux, os_ux, os_sched_last_status, callback, redraw_cb, ignoring_app_if_ux_busy) \ - ux_params.ux_id = BOLOS_UX_EVENT; \ - ux_params.len = 0; \ - os_ux(&ux_params); \ - ux_params.len = os_sched_last_status(TASK_BOLOS_UX); \ - if (ux.asynchmodal_end_callback && os_ux_get_status(BOLOS_UX_ASYNCHMODAL_PAIRING_REQUEST) != 0) \ - { \ - asynchmodal_end_callback_t cb = ux.asynchmodal_end_callback; \ - ux.asynchmodal_end_callback = NULL; \ - cb(os_ux_get_status(BOLOS_UX_ASYNCHMODAL_PAIRING_REQUEST)); \ - } -#endif //HAVE_BOLOS +#define UX_FORWARD_EVENT_REDRAWCB(bypasspincheck, \ + ux_params, \ + ux, \ + os_ux, \ + os_sched_last_status, \ + callback, \ + redraw_cb, \ + ignoring_app_if_ux_busy) \ + ux_params.ux_id = BOLOS_UX_EVENT; \ + ux_params.len = 0; \ + os_ux(&ux_params); \ + ux_params.len = os_sched_last_status(TASK_BOLOS_UX); \ + if (ux.asynchmodal_end_callback \ + && os_ux_get_status(BOLOS_UX_ASYNCHMODAL_PAIRING_REQUEST) != 0) { \ + asynchmodal_end_callback_t cb = ux.asynchmodal_end_callback; \ + ux.asynchmodal_end_callback = NULL; \ + cb(os_ux_get_status(BOLOS_UX_ASYNCHMODAL_PAIRING_REQUEST)); \ + } +#endif // HAVE_BOLOS /** * Request a wake up of the device (pin lock screen, ...) to display a new interface to the user. * Wake up prevents power-off features. Therefore, security wise, this function shall only * be called to request direct user interaction. */ -#define UX_WAKE_UP() \ - G_ux_params.ux_id = BOLOS_UX_WAKE_UP; \ - G_ux_params.len = 0; \ - os_ux(&G_ux_params); \ - G_ux_params.len = os_sched_last_status(TASK_BOLOS_UX); - +#define UX_WAKE_UP() \ + G_ux_params.ux_id = BOLOS_UX_WAKE_UP; \ + G_ux_params.len = 0; \ + os_ux(&G_ux_params); \ + G_ux_params.len = os_sched_last_status(TASK_BOLOS_UX); /** * forward the finger_event to the os ux handler. if not used by it, it will @@ -94,29 +97,32 @@ extern void ux_process_default_event(void); #define UX_FINGER_EVENT(seph_packet) ux_process_finger_event(seph_packet) /** - * forward the ticker_event to the os ux handler. Ticker event callback is always called whatever the return code of the ux app. - * Ticker event interval is assumed to be 100 ms. + * forward the ticker_event to the os ux handler. Ticker event callback is always called whatever + * the return code of the ux app. Ticker event interval is assumed to be 100 ms. */ #define UX_TICKER_EVENT(seph_packet, callback) ux_process_ticker_event() /** - * Forward the event, ignoring the UX return code, the event must therefore be either not processed or processed with extreme care by the application afterwards + * Forward the event, ignoring the UX return code, the event must therefore be either not processed + * or processed with extreme care by the application afterwards */ #define UX_DEFAULT_EVENT() ux_process_default_event() // discriminated from io to allow for different memory placement typedef struct ux_seph_s { - unsigned int button_mask; - unsigned int button_same_mask_counter; + unsigned int button_mask; + unsigned int button_same_mask_counter; #ifdef HAVE_BOLOS - unsigned int ux_id; - unsigned int ux_status; -#endif // HAVE_BOLOS + unsigned int ux_id; + unsigned int ux_status; +#endif // HAVE_BOLOS } ux_seph_os_and_app_t; #ifdef HAVE_BACKGROUND_IMG -SYSCALL PERMISSION(APPLICATION_FLAG_BOLOS_UX) uint8_t *fetch_background_img(bool allow_candidate); -SYSCALL PERMISSION(APPLICATION_FLAG_BOLOS_UX) bolos_err_t delete_background_img(void); +SYSCALL PERMISSION(APPLICATION_FLAG_BOLOS_UX) +uint8_t *fetch_background_img(bool allow_candidate); +SYSCALL PERMISSION(APPLICATION_FLAG_BOLOS_UX) +bolos_err_t delete_background_img(void); #endif extern ux_seph_os_and_app_t G_ux_os; @@ -126,17 +132,19 @@ void io_seproxyhal_power_off(bool criticalBattery); #if defined(HAVE_LANGUAGE_PACK) const char *get_ux_loc_string(UX_LOC_STRINGS_INDEX index); -void bolos_ux_select_language(uint16_t language); -void bolos_ux_refresh_language(void); +void bolos_ux_select_language(uint16_t language); +void bolos_ux_refresh_language(void); typedef struct ux_loc_language_pack_infos { - unsigned char available; + unsigned char available; } UX_LOC_LANGUAGE_PACK_INFO; // To populate infos about language packs -SYSCALL PERMISSION(APPLICATION_FLAG_BOLOS_UX) void list_language_packs(UX_LOC_LANGUAGE_PACK_INFO *packs PLENGTH(NB_LANG*sizeof(UX_LOC_LANGUAGE_PACK_INFO))); -SYSCALL PERMISSION(APPLICATION_FLAG_BOLOS_UX) const LANGUAGE_PACK *get_language_pack(unsigned int language); -#endif //defined(HAVE_LANGUAGE_PACK) +SYSCALL PERMISSION(APPLICATION_FLAG_BOLOS_UX) void list_language_packs( + UX_LOC_LANGUAGE_PACK_INFO *packs PLENGTH(NB_LANG * sizeof(UX_LOC_LANGUAGE_PACK_INFO))); +SYSCALL PERMISSION(APPLICATION_FLAG_BOLOS_UX) const LANGUAGE_PACK *get_language_pack( + unsigned int language); +#endif // defined(HAVE_LANGUAGE_PACK) #include "glyphs.h" diff --git a/lib_ux_stax/ux_loc.h b/lib_ux_stax/ux_loc.h index 791c3667e..c3cd93ed1 100644 --- a/lib_ux_stax/ux_loc.h +++ b/lib_ux_stax/ux_loc.h @@ -1,20 +1,20 @@ /******************************************************************************* -* Ledger Nano S - Secure firmware -* (c) 2022 Ledger -* -* Licensed under the Apache License, Version 2.0 (the "License"); -* you may not use this file except in compliance with the License. -* You may obtain a copy of the License at -* -* http://www.apache.org/licenses/LICENSE-2.0 -* -* Unless required by applicable law or agreed to in writing, software -* distributed under the License is distributed on an "AS IS" BASIS, -* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -* See the License for the specific language governing permissions and -* limitations under the License. -********************************************************************************/ + * Ledger Nano S - Secure firmware + * (c) 2022 Ledger + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + ********************************************************************************/ #pragma once @@ -23,17 +23,17 @@ #if defined(HAVE_LANGUAGE_PACK) // Structure used for language packs: typedef struct language_pack { - uint32_t target_id; // 0x33000004:NanoX, 0x31100004:NanoS 1.5.x etc - uint16_t language; // Language contained in this pack (7000) => use a u_int16_t; +- there are 197 countries in the world, so 1 byte might be enough to store language information, +unless we plan to integrate dialects (>7000) => use a u_int16_t; - we may store some CRC, to check language pack's integrity. */ typedef unsigned short UX_LOC_STRINGS_INDEX; - -#endif //defined(HAVE_LANGUAGE_PACK) +#endif // defined(HAVE_LANGUAGE_PACK) diff --git a/qrcode/include/qrcodegen.h b/qrcode/include/qrcodegen.h index e9ad64c61..dabf93879 100644 --- a/qrcode/include/qrcodegen.h +++ b/qrcode/include/qrcodegen.h @@ -27,12 +27,10 @@ #include #include - #ifdef __cplusplus extern "C" { #endif - /* * This library creates QR Code symbols, which is a type of two-dimension barcode. * Invented by Denso Wave and described in the ISO/IEC 18004 standard. @@ -45,57 +43,54 @@ extern "C" { * - High level: Take the payload data and call qrcodegen_encodeText() or qrcodegen_encodeBinary(). * - Low level: Custom-make the list of segments and call * qrcodegen_encodeSegments() or qrcodegen_encodeSegmentsAdvanced(). - * (Note that all ways require supplying the desired error correction level and various byte buffers.) + * (Note that all ways require supplying the desired error correction level and various byte + * buffers.) */ - /*---- Enum and struct types----*/ /* * The error correction level in a QR Code symbol. */ enum qrcodegen_Ecc { - // Must be declared in ascending order of error protection - // so that an internal qrcodegen function works properly - qrcodegen_Ecc_INVALID = -1, // This value was added to avoid compilation warnings -Wtype-limits - qrcodegen_Ecc_LOW , // The QR Code can tolerate about 7% erroneous codewords - qrcodegen_Ecc_MEDIUM , // The QR Code can tolerate about 15% erroneous codewords - qrcodegen_Ecc_QUARTILE, // The QR Code can tolerate about 25% erroneous codewords - qrcodegen_Ecc_HIGH , // The QR Code can tolerate about 30% erroneous codewords + // Must be declared in ascending order of error protection + // so that an internal qrcodegen function works properly + qrcodegen_Ecc_INVALID = -1, // This value was added to avoid compilation warnings -Wtype-limits + qrcodegen_Ecc_LOW, // The QR Code can tolerate about 7% erroneous codewords + qrcodegen_Ecc_MEDIUM, // The QR Code can tolerate about 15% erroneous codewords + qrcodegen_Ecc_QUARTILE, // The QR Code can tolerate about 25% erroneous codewords + qrcodegen_Ecc_HIGH, // The QR Code can tolerate about 30% erroneous codewords }; - /* * The mask pattern used in a QR Code symbol. */ enum qrcodegen_Mask { - // A special value to tell the QR Code encoder to - // automatically select an appropriate mask pattern - qrcodegen_Mask_AUTO = -1, - // The eight actual mask patterns - qrcodegen_Mask_0 = 0, - qrcodegen_Mask_1, - qrcodegen_Mask_2, - qrcodegen_Mask_3, - qrcodegen_Mask_4, - qrcodegen_Mask_5, - qrcodegen_Mask_6, - qrcodegen_Mask_7, + // A special value to tell the QR Code encoder to + // automatically select an appropriate mask pattern + qrcodegen_Mask_AUTO = -1, + // The eight actual mask patterns + qrcodegen_Mask_0 = 0, + qrcodegen_Mask_1, + qrcodegen_Mask_2, + qrcodegen_Mask_3, + qrcodegen_Mask_4, + qrcodegen_Mask_5, + qrcodegen_Mask_6, + qrcodegen_Mask_7, }; - /* * Describes how a segment's data bits are interpreted. */ enum qrcodegen_Mode { - qrcodegen_Mode_NUMERIC = 0x1, - qrcodegen_Mode_ALPHANUMERIC = 0x2, - qrcodegen_Mode_BYTE = 0x4, - qrcodegen_Mode_KANJI = 0x8, - qrcodegen_Mode_ECI = 0x7, + qrcodegen_Mode_NUMERIC = 0x1, + qrcodegen_Mode_ALPHANUMERIC = 0x2, + qrcodegen_Mode_BYTE = 0x4, + qrcodegen_Mode_KANJI = 0x8, + qrcodegen_Mode_ECI = 0x7, }; - /* * A segment of character/binary/control data in a QR Code symbol. * The mid-level way to create a segment is to take the payload data @@ -108,43 +103,42 @@ enum qrcodegen_Mode { * the largest QR Code (version 40) has 31329 modules. */ struct qrcodegen_Segment { - // The mode indicator of this segment. - enum qrcodegen_Mode mode; - - // The length of this segment's unencoded data. Measured in characters for - // numeric/alphanumeric/kanji mode, bytes for byte mode, and 0 for ECI mode. - // Always zero or positive. Not the same as the data's bit length. - int numChars; - - // The data bits of this segment, packed in bitwise big endian. - // Can be null if the bit length is zero. - uint8_t *data; - - // The number of valid data bits used in the buffer. Requires - // 0 <= bitLength <= 32767, and bitLength <= (capacity of data array) * 8. - // The character count (numChars) must agree with the mode and the bit buffer length. - int bitLength; + // The mode indicator of this segment. + enum qrcodegen_Mode mode; + + // The length of this segment's unencoded data. Measured in characters for + // numeric/alphanumeric/kanji mode, bytes for byte mode, and 0 for ECI mode. + // Always zero or positive. Not the same as the data's bit length. + int numChars; + + // The data bits of this segment, packed in bitwise big endian. + // Can be null if the bit length is zero. + uint8_t *data; + + // The number of valid data bits used in the buffer. Requires + // 0 <= bitLength <= 32767, and bitLength <= (capacity of data array) * 8. + // The character count (numChars) must agree with the mode and the bit buffer length. + int bitLength; }; - - /*---- Macro constants and functions ----*/ -#define qrcodegen_VERSION_MIN 4 // The minimum version number supported in the QR Code Model 2 standard -#define qrcodegen_VERSION_MAX 10 // The maximum version number supported in the QR Code Model 2 standard +#define qrcodegen_VERSION_MIN \ + 4 // The minimum version number supported in the QR Code Model 2 standard +#define qrcodegen_VERSION_MAX \ + 10 // The maximum version number supported in the QR Code Model 2 standard -// Calculates the number of bytes needed to store any QR Code up to and including the given version number, -// as a compile-time constant. For example, 'uint8_t buffer[qrcodegen_BUFFER_LEN_FOR_VERSION(25)];' -// can store any single QR Code from version 1 to 25 (inclusive). The result fits in an int (or int16). -// Requires qrcodegen_VERSION_MIN <= n <= qrcodegen_VERSION_MAX. -#define qrcodegen_BUFFER_LEN_FOR_VERSION(n) ((((n) * 4 + 17) * ((n) * 4 + 17) + 7) / 8 + 1) +// Calculates the number of bytes needed to store any QR Code up to and including the given version +// number, as a compile-time constant. For example, 'uint8_t +// buffer[qrcodegen_BUFFER_LEN_FOR_VERSION(25)];' can store any single QR Code from version 1 to 25 +// (inclusive). The result fits in an int (or int16). Requires qrcodegen_VERSION_MIN <= n <= +// qrcodegen_VERSION_MAX. +#define qrcodegen_BUFFER_LEN_FOR_VERSION(n) ((((n) *4 + 17) * ((n) *4 + 17) + 7) / 8 + 1) // The worst-case number of bytes needed to store one QR Code, up to and including // version 40. This value equals 3918, which is just under 4 kilobytes. // Use this more convenient value to avoid calculating tighter memory bounds for buffers. -#define qrcodegen_BUFFER_LEN_MAX qrcodegen_BUFFER_LEN_FOR_VERSION(qrcodegen_VERSION_MAX) - - +#define qrcodegen_BUFFER_LEN_MAX qrcodegen_BUFFER_LEN_FOR_VERSION(qrcodegen_VERSION_MAX) /*---- Functions (high level) to generate QR Codes ----*/ @@ -167,9 +161,14 @@ struct qrcodegen_Segment { * - Please consult the QR Code specification for information on * data capacities per version, ECC level, and text encoding mode. */ -bool qrcodegen_encodeText(const char *text, uint8_t tempBuffer[], uint8_t qrcode[], - enum qrcodegen_Ecc ecl, int minVersion, int maxVersion, enum qrcodegen_Mask mask, bool boostEcl); - +bool qrcodegen_encodeText(const char *text, + uint8_t tempBuffer[], + uint8_t qrcode[], + enum qrcodegen_Ecc ecl, + int minVersion, + int maxVersion, + enum qrcodegen_Mask mask, + bool boostEcl); /* * Encodes the given binary data to a QR Code, returning true if encoding succeeded. @@ -189,9 +188,14 @@ bool qrcodegen_encodeText(const char *text, uint8_t tempBuffer[], uint8_t qrcode * - Please consult the QR Code specification for information on * data capacities per version, ECC level, and text encoding mode. */ -bool qrcodegen_encodeBinary(uint8_t dataAndTemp[], size_t dataLen, uint8_t qrcode[], - enum qrcodegen_Ecc ecl, int minVersion, int maxVersion, enum qrcodegen_Mask mask, bool boostEcl); - +bool qrcodegen_encodeBinary(uint8_t dataAndTemp[], + size_t dataLen, + uint8_t qrcode[], + enum qrcodegen_Ecc ecl, + int minVersion, + int maxVersion, + enum qrcodegen_Mask mask, + bool boostEcl); /*---- Functions (low level) to generate QR Codes ----*/ @@ -199,36 +203,43 @@ bool qrcodegen_encodeBinary(uint8_t dataAndTemp[], size_t dataLen, uint8_t qrcod * Renders a QR Code representing the given segments at the given error correction level. * The smallest possible QR Code version is automatically chosen for the output. Returns true if * QR Code creation succeeded, or false if the data is too long to fit in any version. The ECC level - * of the result may be higher than the ecl argument if it can be done without increasing the version. - * This function allows the user to create a custom sequence of segments that switches + * of the result may be higher than the ecl argument if it can be done without increasing the + * version. This function allows the user to create a custom sequence of segments that switches * between modes (such as alphanumeric and byte) to encode text in less space. - * This is a low-level API; the high-level API is qrcodegen_encodeText() and qrcodegen_encodeBinary(). - * To save memory, the segments' data buffers can alias/overlap tempBuffer, and will - * result in them being clobbered, but the QR Code output will still be correct. - * But the qrcode array must not overlap tempBuffer or any segment's data buffer. + * This is a low-level API; the high-level API is qrcodegen_encodeText() and + * qrcodegen_encodeBinary(). To save memory, the segments' data buffers can alias/overlap + * tempBuffer, and will result in them being clobbered, but the QR Code output will still be + * correct. But the qrcode array must not overlap tempBuffer or any segment's data buffer. */ -bool qrcodegen_encodeSegments(const struct qrcodegen_Segment segs[], size_t len, - enum qrcodegen_Ecc ecl, uint8_t tempBuffer[], uint8_t qrcode[]); - +bool qrcodegen_encodeSegments(const struct qrcodegen_Segment segs[], + size_t len, + enum qrcodegen_Ecc ecl, + uint8_t tempBuffer[], + uint8_t qrcode[]); /* * Renders a QR Code representing the given segments with the given encoding parameters. - * Returns true if QR Code creation succeeded, or false if the data is too long to fit in the range of versions. - * The smallest possible QR Code version within the given range is automatically - * chosen for the output. Iff boostEcl is true, then the ECC level of the result - * may be higher than the ecl argument if it can be done without increasing the - * version. The mask is either between qrcodegen_Mask_0 to 7 to force that mask, or - * qrcodegen_Mask_AUTO to automatically choose an appropriate mask (which may be slow). - * This function allows the user to create a custom sequence of segments that switches - * between modes (such as alphanumeric and byte) to encode text in less space. - * This is a low-level API; the high-level API is qrcodegen_encodeText() and qrcodegen_encodeBinary(). - * To save memory, the segments' data buffers can alias/overlap tempBuffer, and will - * result in them being clobbered, but the QR Code output will still be correct. - * But the qrcode array must not overlap tempBuffer or any segment's data buffer. + * Returns true if QR Code creation succeeded, or false if the data is too long to fit in the range + * of versions. The smallest possible QR Code version within the given range is automatically chosen + * for the output. Iff boostEcl is true, then the ECC level of the result may be higher than the ecl + * argument if it can be done without increasing the version. The mask is either between + * qrcodegen_Mask_0 to 7 to force that mask, or qrcodegen_Mask_AUTO to automatically choose an + * appropriate mask (which may be slow). This function allows the user to create a custom sequence + * of segments that switches between modes (such as alphanumeric and byte) to encode text in less + * space. This is a low-level API; the high-level API is qrcodegen_encodeText() and + * qrcodegen_encodeBinary(). To save memory, the segments' data buffers can alias/overlap + * tempBuffer, and will result in them being clobbered, but the QR Code output will still be + * correct. But the qrcode array must not overlap tempBuffer or any segment's data buffer. */ -bool qrcodegen_encodeSegmentsAdvanced(const struct qrcodegen_Segment segs[], size_t len, enum qrcodegen_Ecc ecl, - int minVersion, int maxVersion, enum qrcodegen_Mask mask, bool boostEcl, uint8_t tempBuffer[], uint8_t qrcode[]); - +bool qrcodegen_encodeSegmentsAdvanced(const struct qrcodegen_Segment segs[], + size_t len, + enum qrcodegen_Ecc ecl, + int minVersion, + int maxVersion, + enum qrcodegen_Mask mask, + bool boostEcl, + uint8_t tempBuffer[], + uint8_t qrcode[]); /* * Tests whether the given string can be encoded as a segment in numeric mode. @@ -236,7 +247,6 @@ bool qrcodegen_encodeSegmentsAdvanced(const struct qrcodegen_Segment segs[], siz */ bool qrcodegen_isNumeric(const char *text); - /* * Tests whether the given string can be encoded as a segment in alphanumeric mode. * A string is encodable iff each character is in the following set: 0 to 9, A to Z @@ -244,7 +254,6 @@ bool qrcodegen_isNumeric(const char *text); */ bool qrcodegen_isAlphanumeric(const char *text); - /* * Returns the number of bytes (uint8_t) needed for the data buffer of a segment * containing the given number of characters using the given mode. Notes: @@ -258,7 +267,6 @@ bool qrcodegen_isAlphanumeric(const char *text); */ size_t qrcodegen_calcSegmentBufferSize(enum qrcodegen_Mode mode, size_t numChars); - /* * Returns a segment representing the given binary data encoded in * byte mode. All input byte arrays are acceptable. Any text string @@ -266,13 +274,11 @@ size_t qrcodegen_calcSegmentBufferSize(enum qrcodegen_Mode mode, size_t numChars */ struct qrcodegen_Segment qrcodegen_makeBytes(const uint8_t data[], size_t len, uint8_t buf[]); - /* * Returns a segment representing the given string of decimal digits encoded in numeric mode. */ struct qrcodegen_Segment qrcodegen_makeNumeric(const char *digits, uint8_t buf[]); - /* * Returns a segment representing the given text string encoded in alphanumeric mode. * The characters allowed are: 0 to 9, A to Z (uppercase only), space, @@ -280,14 +286,12 @@ struct qrcodegen_Segment qrcodegen_makeNumeric(const char *digits, uint8_t buf[] */ struct qrcodegen_Segment qrcodegen_makeAlphanumeric(const char *text, uint8_t buf[]); - /* * Returns a segment representing an Extended Channel Interpretation * (ECI) designator with the given assignment value. */ struct qrcodegen_Segment qrcodegen_makeEci(long assignVal, uint8_t buf[]); - /*---- Functions to extract raw data from QR Codes ----*/ /* @@ -298,7 +302,6 @@ struct qrcodegen_Segment qrcodegen_makeEci(long assignVal, uint8_t buf[]); */ int qrcodegen_getSize(const uint8_t qrcode[]); - /* * Returns the color of the module (pixel) at the given coordinates, which is false * for light or true for dark. The top left corner has the coordinates (x=0, y=0). @@ -306,7 +309,6 @@ int qrcodegen_getSize(const uint8_t qrcode[]); */ bool qrcodegen_getModule(const uint8_t qrcode[], int x, int y); - #ifdef __cplusplus } #endif diff --git a/qrcode/src/qrcodegen.c b/qrcode/src/qrcodegen.c index 513475278..3afa6b721 100644 --- a/qrcode/src/qrcodegen.c +++ b/qrcode/src/qrcodegen.c @@ -28,15 +28,17 @@ #include "os_task.h" #ifndef QRCODEGEN_TEST - #define testable static // Keep functions private +#define testable static // Keep functions private #else - #define testable // Expose private functions +#define testable // Expose private functions #endif - -#define assert(x) if(!(x)) {\ - os_sched_exit(-1); \ - for(;;);} +#define assert(x) \ + if (!(x)) { \ + os_sched_exit(-1); \ + for (;;) \ + ; \ + } /*---- Forward declarations for private functions ----*/ @@ -58,790 +60,924 @@ testable void appendBitsToBuffer(unsigned int val, int numBits, uint8_t buffer[], int *bitLen); -testable void addEccAndInterleave(uint8_t data[], int version, enum qrcodegen_Ecc ecl, uint8_t result[]); -testable int getNumDataCodewords(int version, enum qrcodegen_Ecc ecl); -testable int getNumRawDataModules(int ver); - -testable void reedSolomonComputeDivisor(int degree, uint8_t result[]); -testable void reedSolomonComputeRemainder(const uint8_t data[], int dataLen, - const uint8_t generator[], int degree, uint8_t result[]); +testable void addEccAndInterleave(uint8_t data[], + int version, + enum qrcodegen_Ecc ecl, + uint8_t result[]); +testable int getNumDataCodewords(int version, enum qrcodegen_Ecc ecl); +testable int getNumRawDataModules(int ver); + +testable void reedSolomonComputeDivisor(int degree, uint8_t result[]); +testable void reedSolomonComputeRemainder(const uint8_t data[], + int dataLen, + const uint8_t generator[], + int degree, + uint8_t result[]); testable uint8_t reedSolomonMultiply(uint8_t x, uint8_t y); testable void initializeFunctionModules(int version, uint8_t qrcode[]); -static void drawLightFunctionModules(uint8_t qrcode[], int version); -static void drawFormatBits(enum qrcodegen_Ecc ecl, enum qrcodegen_Mask mask, uint8_t qrcode[]); -testable int getAlignmentPatternPositions(int version, uint8_t result[7]); -static void fillRectangle(int left, int top, int width, int height, uint8_t qrcode[]); +static void drawLightFunctionModules(uint8_t qrcode[], int version); +static void drawFormatBits(enum qrcodegen_Ecc ecl, enum qrcodegen_Mask mask, uint8_t qrcode[]); +testable int getAlignmentPatternPositions(int version, uint8_t result[7]); +static void fillRectangle(int left, int top, int width, int height, uint8_t qrcode[]); static void drawCodewords(const uint8_t data[], int dataLen, uint8_t qrcode[]); static void applyMask(const uint8_t functionModules[], uint8_t qrcode[], enum qrcodegen_Mask mask); static long getPenaltyScore(const uint8_t qrcode[]); -static int finderPenaltyCountPatterns(const int runHistory[7], int qrsize); -static int finderPenaltyTerminateAndCount(bool currentRunColor, int currentRunLength, int runHistory[7], int qrsize); +static int finderPenaltyCountPatterns(const int runHistory[7], int qrsize); +static int finderPenaltyTerminateAndCount(bool currentRunColor, + int currentRunLength, + int runHistory[7], + int qrsize); static void finderPenaltyAddHistory(int currentRunLength, int runHistory[7], int qrsize); testable bool getModuleBounded(const uint8_t qrcode[], int x, int y); testable void setModuleBounded(uint8_t qrcode[], int x, int y, bool isDark); testable void setModuleUnbounded(uint8_t qrcode[], int x, int y, bool isDark); -static bool getBit(int x, int i); +static bool getBit(int x, int i); testable int calcSegmentBitLength(enum qrcodegen_Mode mode, size_t numChars); testable int getTotalBits(const struct qrcodegen_Segment segs[], size_t len, int version); -static int numCharCountBits(enum qrcodegen_Mode mode, int version); - - +static int numCharCountBits(enum qrcodegen_Mode mode, int version); /*---- Private tables of constants ----*/ // The set of all legal characters in alphanumeric mode, where each character // value maps to the index in the string. For checking text and encoding segments. -static const char * const ALPHANUMERIC_CHARSET = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ $%*+-./:"; +static const char *const ALPHANUMERIC_CHARSET = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ $%*+-./:"; // For generating error correction codes. testable const int8_t ECC_CODEWORDS_PER_BLOCK[4][41] = { - // Version: (note that index 0 is for padding, and is set to an illegal value) - //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, 32, 33, 34, 35, 36, 37, 38, 39, 40 Error correction level - {-1, 7, 10, 15, 20, 26, 18, 20, 24, 30, 18, 20, 24, 26, 30, 22, 24, 28, 30, 28, 28, 28, 28, 30, 30, 26, 28, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30}, // Low - {-1, 10, 16, 26, 18, 24, 16, 18, 22, 22, 26, 30, 22, 22, 24, 24, 28, 28, 26, 26, 26, 26, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28}, // Medium - {-1, 13, 22, 18, 26, 18, 24, 18, 22, 20, 24, 28, 26, 24, 20, 30, 24, 28, 28, 26, 30, 28, 30, 30, 30, 30, 28, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30}, // Quartile - {-1, 17, 28, 22, 16, 22, 28, 26, 26, 24, 28, 24, 28, 22, 24, 24, 30, 28, 28, 26, 28, 30, 24, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30}, // High + // Version: (note that index 0 is for padding, and is set to an illegal value) + // 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, 32, 33, 34, 35, 36, 37, 38, 39, 40 Error correction + // level + {-1, 7, 10, 15, 20, 26, 18, 20, 24, 30, 18, 20, 24, 26, 30, 22, 24, 28, 30, 28, 28, + 28, 28, 30, 30, 26, 28, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30}, // Low + {-1, 10, 16, 26, 18, 24, 16, 18, 22, 22, 26, 30, 22, 22, 24, 24, 28, 28, 26, 26, 26, + 26, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28}, // Medium + {-1, 13, 22, 18, 26, 18, 24, 18, 22, 20, 24, 28, 26, 24, 20, 30, 24, 28, 28, 26, 30, + 28, 30, 30, 30, 30, 28, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30}, // Quartile + {-1, 17, 28, 22, 16, 22, 28, 26, 26, 24, 28, 24, 28, 22, 24, 24, 30, 28, 28, 26, 28, + 30, 24, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30}, // High }; #define qrcodegen_REED_SOLOMON_DEGREE_MAX 30 // Based on the table above // For generating error correction codes. testable const int8_t NUM_ERROR_CORRECTION_BLOCKS[4][41] = { - // Version: (note that index 0 is for padding, and is set to an illegal value) - //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, 32, 33, 34, 35, 36, 37, 38, 39, 40 Error correction level - {-1, 1, 1, 1, 1, 1, 2, 2, 2, 2, 4, 4, 4, 4, 4, 6, 6, 6, 6, 7, 8, 8, 9, 9, 10, 12, 12, 12, 13, 14, 15, 16, 17, 18, 19, 19, 20, 21, 22, 24, 25}, // Low - {-1, 1, 1, 1, 2, 2, 4, 4, 4, 5, 5, 5, 8, 9, 9, 10, 10, 11, 13, 14, 16, 17, 17, 18, 20, 21, 23, 25, 26, 28, 29, 31, 33, 35, 37, 38, 40, 43, 45, 47, 49}, // Medium - {-1, 1, 1, 2, 2, 4, 4, 6, 6, 8, 8, 8, 10, 12, 16, 12, 17, 16, 18, 21, 20, 23, 23, 25, 27, 29, 34, 34, 35, 38, 40, 43, 45, 48, 51, 53, 56, 59, 62, 65, 68}, // Quartile - {-1, 1, 1, 2, 4, 4, 4, 5, 6, 8, 8, 11, 11, 16, 16, 18, 16, 19, 21, 25, 25, 25, 34, 30, 32, 35, 37, 40, 42, 45, 48, 51, 54, 57, 60, 63, 66, 70, 74, 77, 81}, // High + // Version: (note that index 0 is for padding, and is set to an illegal value) + // 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, 32, 33, 34, 35, 36, 37, 38, 39, 40 Error correction level + {-1, 1, 1, 1, 1, 1, 2, 2, 2, 2, 4, 4, 4, 4, 4, 6, 6, 6, 6, 7, 8, + 8, 9, 9, 10, 12, 12, 12, 13, 14, 15, 16, 17, 18, 19, 19, 20, 21, 22, 24, 25}, // Low + {-1, 1, 1, 1, 2, 2, 4, 4, 4, 5, 5, 5, 8, 9, 9, 10, 10, 11, 13, 14, 16, + 17, 17, 18, 20, 21, 23, 25, 26, 28, 29, 31, 33, 35, 37, 38, 40, 43, 45, 47, 49}, // Medium + {-1, 1, 1, 2, 2, 4, 4, 6, 6, 8, 8, 8, 10, 12, 16, 12, 17, 16, 18, 21, 20, + 23, 23, 25, 27, 29, 34, 34, 35, 38, 40, 43, 45, 48, 51, 53, 56, 59, 62, 65, 68}, // Quartile + {-1, 1, 1, 2, 4, 4, 4, 5, 6, 8, 8, 11, 11, 16, 16, 18, 16, 19, 21, 25, 25, + 25, 34, 30, 32, 35, 37, 40, 42, 45, 48, 51, 54, 57, 60, 63, 66, 70, 74, 77, 81}, // High }; // For automatic mask pattern selection. -static const int PENALTY_N1 = 3; -static const int PENALTY_N2 = 3; +static const int PENALTY_N1 = 3; +static const int PENALTY_N2 = 3; static const int PENALTY_N3 = 40; static const int PENALTY_N4 = 10; - - /*---- High-level QR Code encoding functions ----*/ // Public function - see documentation comment in header file. -bool qrcodegen_encodeText(const char *text, uint8_t tempBuffer[], uint8_t qrcode[], - enum qrcodegen_Ecc ecl, int minVersion, int maxVersion, enum qrcodegen_Mask mask, bool boostEcl) { - - size_t textLen = strlen(text); - if (textLen == 0) - return qrcodegen_encodeSegmentsAdvanced(NULL, 0, ecl, minVersion, maxVersion, mask, boostEcl, tempBuffer, qrcode); - size_t bufLen = (size_t)qrcodegen_BUFFER_LEN_FOR_VERSION(maxVersion); - - struct qrcodegen_Segment seg; - if (qrcodegen_isNumeric(text)) { - if (qrcodegen_calcSegmentBufferSize(qrcodegen_Mode_NUMERIC, textLen) > bufLen) - goto fail; - seg = qrcodegen_makeNumeric(text, tempBuffer); - } else if (qrcodegen_isAlphanumeric(text)) { - if (qrcodegen_calcSegmentBufferSize(qrcodegen_Mode_ALPHANUMERIC, textLen) > bufLen) - goto fail; - seg = qrcodegen_makeAlphanumeric(text, tempBuffer); - } else { - if (textLen > bufLen) - goto fail; - for (size_t i = 0; i < textLen; i++) - tempBuffer[i] = (uint8_t)text[i]; - seg.mode = qrcodegen_Mode_BYTE; - seg.bitLength = calcSegmentBitLength(seg.mode, textLen); - if (seg.bitLength == -1) - goto fail; - seg.numChars = (int)textLen; - seg.data = tempBuffer; - } - return qrcodegen_encodeSegmentsAdvanced(&seg, 1, ecl, minVersion, maxVersion, mask, boostEcl, tempBuffer, qrcode); +bool qrcodegen_encodeText(const char *text, + uint8_t tempBuffer[], + uint8_t qrcode[], + enum qrcodegen_Ecc ecl, + int minVersion, + int maxVersion, + enum qrcodegen_Mask mask, + bool boostEcl) +{ + size_t textLen = strlen(text); + if (textLen == 0) { + return qrcodegen_encodeSegmentsAdvanced( + NULL, 0, ecl, minVersion, maxVersion, mask, boostEcl, tempBuffer, qrcode); + } + size_t bufLen = (size_t) qrcodegen_BUFFER_LEN_FOR_VERSION(maxVersion); + + struct qrcodegen_Segment seg; + if (qrcodegen_isNumeric(text)) { + if (qrcodegen_calcSegmentBufferSize(qrcodegen_Mode_NUMERIC, textLen) > bufLen) { + goto fail; + } + seg = qrcodegen_makeNumeric(text, tempBuffer); + } + else if (qrcodegen_isAlphanumeric(text)) { + if (qrcodegen_calcSegmentBufferSize(qrcodegen_Mode_ALPHANUMERIC, textLen) > bufLen) { + goto fail; + } + seg = qrcodegen_makeAlphanumeric(text, tempBuffer); + } + else { + if (textLen > bufLen) { + goto fail; + } + for (size_t i = 0; i < textLen; i++) { + tempBuffer[i] = (uint8_t) text[i]; + } + seg.mode = qrcodegen_Mode_BYTE; + seg.bitLength = calcSegmentBitLength(seg.mode, textLen); + if (seg.bitLength == -1) { + goto fail; + } + seg.numChars = (int) textLen; + seg.data = tempBuffer; + } + return qrcodegen_encodeSegmentsAdvanced( + &seg, 1, ecl, minVersion, maxVersion, mask, boostEcl, tempBuffer, qrcode); fail: - qrcode[0] = 0; // Set size to invalid value for safety - return false; + qrcode[0] = 0; // Set size to invalid value for safety + return false; } - // Public function - see documentation comment in header file. -bool qrcodegen_encodeBinary(uint8_t dataAndTemp[], size_t dataLen, uint8_t qrcode[], - enum qrcodegen_Ecc ecl, int minVersion, int maxVersion, enum qrcodegen_Mask mask, bool boostEcl) { - - struct qrcodegen_Segment seg; - seg.mode = qrcodegen_Mode_BYTE; - seg.bitLength = calcSegmentBitLength(seg.mode, dataLen); - if (seg.bitLength == -1) { - qrcode[0] = 0; // Set size to invalid value for safety - return false; - } - seg.numChars = (int)dataLen; - seg.data = dataAndTemp; - return qrcodegen_encodeSegmentsAdvanced(&seg, 1, ecl, minVersion, maxVersion, mask, boostEcl, dataAndTemp, qrcode); +bool qrcodegen_encodeBinary(uint8_t dataAndTemp[], + size_t dataLen, + uint8_t qrcode[], + enum qrcodegen_Ecc ecl, + int minVersion, + int maxVersion, + enum qrcodegen_Mask mask, + bool boostEcl) +{ + struct qrcodegen_Segment seg; + seg.mode = qrcodegen_Mode_BYTE; + seg.bitLength = calcSegmentBitLength(seg.mode, dataLen); + if (seg.bitLength == -1) { + qrcode[0] = 0; // Set size to invalid value for safety + return false; + } + seg.numChars = (int) dataLen; + seg.data = dataAndTemp; + return qrcodegen_encodeSegmentsAdvanced( + &seg, 1, ecl, minVersion, maxVersion, mask, boostEcl, dataAndTemp, qrcode); } - // Appends the given number of low-order bits of the given value to the given byte-based // bit buffer, increasing the bit length. Requires 0 <= numBits <= 16 and val < 2^numBits. -testable void appendBitsToBuffer(unsigned int val, int numBits, uint8_t buffer[], int *bitLen) { - assert(0 <= numBits && numBits <= 16 && (unsigned long)val >> numBits == 0); - for (int i = numBits - 1; i >= 0; i--, (*bitLen)++) - buffer[*bitLen >> 3] |= ((val >> i) & 1) << (7 - (*bitLen & 7)); +testable void appendBitsToBuffer(unsigned int val, int numBits, uint8_t buffer[], int *bitLen) +{ + assert(0 <= numBits && numBits <= 16 && (unsigned long) val >> numBits == 0); + for (int i = numBits - 1; i >= 0; i--, (*bitLen)++) { + buffer[*bitLen >> 3] |= ((val >> i) & 1) << (7 - (*bitLen & 7)); + } } - - /*---- Low-level QR Code encoding functions ----*/ // Public function - see documentation comment in header file. -bool qrcodegen_encodeSegments(const struct qrcodegen_Segment segs[], size_t len, - enum qrcodegen_Ecc ecl, uint8_t tempBuffer[], uint8_t qrcode[]) { - return qrcodegen_encodeSegmentsAdvanced(segs, len, ecl, - qrcodegen_VERSION_MIN, qrcodegen_VERSION_MAX, qrcodegen_Mask_AUTO, true, tempBuffer, qrcode); +bool qrcodegen_encodeSegments(const struct qrcodegen_Segment segs[], + size_t len, + enum qrcodegen_Ecc ecl, + uint8_t tempBuffer[], + uint8_t qrcode[]) +{ + return qrcodegen_encodeSegmentsAdvanced(segs, + len, + ecl, + qrcodegen_VERSION_MIN, + qrcodegen_VERSION_MAX, + qrcodegen_Mask_AUTO, + true, + tempBuffer, + qrcode); } - // Public function - see documentation comment in header file. -bool qrcodegen_encodeSegmentsAdvanced(const struct qrcodegen_Segment segs[], size_t len, enum qrcodegen_Ecc ecl, - int minVersion, int maxVersion, enum qrcodegen_Mask mask, bool boostEcl, uint8_t tempBuffer[], uint8_t qrcode[]) { - assert(segs != NULL || len == 0); - assert(qrcodegen_VERSION_MIN <= minVersion && minVersion <= maxVersion && maxVersion <= qrcodegen_VERSION_MAX); - assert(0 <= (int)ecl && (int)ecl <= 3 && -1 <= (int)mask && (int)mask <= 7); - - // Find the minimal version number to use - int version, dataUsedBits; - for (version = minVersion; ; version++) { - int dataCapacityBits = getNumDataCodewords(version, ecl) * 8; // Number of data bits available - dataUsedBits = getTotalBits(segs, len, version); - if (dataUsedBits != -1 && dataUsedBits <= dataCapacityBits) - break; // This version number is found to be suitable - if (version >= maxVersion) { // All versions in the range could not fit the given data - qrcode[0] = 0; // Set size to invalid value for safety - return false; - } - } - assert(dataUsedBits != -1); - - // Increase the error correction level while the data still fits in the current version number - for (int i = (int)qrcodegen_Ecc_MEDIUM; i <= (int)qrcodegen_Ecc_HIGH; i++) { // From low to high - if (boostEcl && dataUsedBits <= getNumDataCodewords(version, (enum qrcodegen_Ecc)i) * 8) - ecl = (enum qrcodegen_Ecc)i; - } - - // Concatenate all segments to create the data bit string - memset(qrcode, 0, (size_t)qrcodegen_BUFFER_LEN_FOR_VERSION(version) * sizeof(qrcode[0])); - int bitLen = 0; - for (size_t i = 0; i < len; i++) { - const struct qrcodegen_Segment *seg = &segs[i]; - appendBitsToBuffer((unsigned int)seg->mode, 4, qrcode, &bitLen); - appendBitsToBuffer((unsigned int)seg->numChars, numCharCountBits(seg->mode, version), qrcode, &bitLen); - for (int j = 0; j < seg->bitLength; j++) { - int bit = (seg->data[j >> 3] >> (7 - (j & 7))) & 1; - appendBitsToBuffer((unsigned int)bit, 1, qrcode, &bitLen); - } - } - assert(bitLen == dataUsedBits); - - // Add terminator and pad up to a byte if applicable - int dataCapacityBits = getNumDataCodewords(version, ecl) * 8; - assert(bitLen <= dataCapacityBits); - int terminatorBits = dataCapacityBits - bitLen; - if (terminatorBits > 4) - terminatorBits = 4; - appendBitsToBuffer(0, terminatorBits, qrcode, &bitLen); - appendBitsToBuffer(0, (8 - bitLen % 8) % 8, qrcode, &bitLen); - assert(bitLen % 8 == 0); - - // Pad with alternating bytes until data capacity is reached - for (uint8_t padByte = 0xEC; bitLen < dataCapacityBits; padByte ^= 0xEC ^ 0x11) - appendBitsToBuffer(padByte, 8, qrcode, &bitLen); - - // Compute ECC, draw modules - addEccAndInterleave(qrcode, version, ecl, tempBuffer); - initializeFunctionModules(version, qrcode); - drawCodewords(tempBuffer, getNumRawDataModules(version) / 8, qrcode); - drawLightFunctionModules(qrcode, version); - initializeFunctionModules(version, tempBuffer); - - // Do masking - if (mask == qrcodegen_Mask_AUTO) { // Automatically choose best mask - long minPenalty = LONG_MAX; - for (int i = 0; i < 8; i++) { - enum qrcodegen_Mask msk = (enum qrcodegen_Mask)i; - applyMask(tempBuffer, qrcode, msk); - drawFormatBits(ecl, msk, qrcode); - long penalty = getPenaltyScore(qrcode); - if (penalty < minPenalty) { - mask = msk; - minPenalty = penalty; - } - applyMask(tempBuffer, qrcode, msk); // Undoes the mask due to XOR - } - } - assert(0 <= (int)mask && (int)mask <= 7); - applyMask(tempBuffer, qrcode, mask); // Apply the final choice of mask - drawFormatBits(ecl, mask, qrcode); // Overwrite old format bits - return true; +bool qrcodegen_encodeSegmentsAdvanced(const struct qrcodegen_Segment segs[], + size_t len, + enum qrcodegen_Ecc ecl, + int minVersion, + int maxVersion, + enum qrcodegen_Mask mask, + bool boostEcl, + uint8_t tempBuffer[], + uint8_t qrcode[]) +{ + assert(segs != NULL || len == 0); + assert(qrcodegen_VERSION_MIN <= minVersion && minVersion <= maxVersion + && maxVersion <= qrcodegen_VERSION_MAX); + assert(0 <= (int) ecl && (int) ecl <= 3 && -1 <= (int) mask && (int) mask <= 7); + + // Find the minimal version number to use + int version, dataUsedBits; + for (version = minVersion;; version++) { + int dataCapacityBits + = getNumDataCodewords(version, ecl) * 8; // Number of data bits available + dataUsedBits = getTotalBits(segs, len, version); + if (dataUsedBits != -1 && dataUsedBits <= dataCapacityBits) { + break; // This version number is found to be suitable + } + if (version >= maxVersion) { // All versions in the range could not fit the given data + qrcode[0] = 0; // Set size to invalid value for safety + return false; + } + } + assert(dataUsedBits != -1); + + // Increase the error correction level while the data still fits in the current version number + for (int i = (int) qrcodegen_Ecc_MEDIUM; i <= (int) qrcodegen_Ecc_HIGH; + i++) { // From low to high + if (boostEcl && dataUsedBits <= getNumDataCodewords(version, (enum qrcodegen_Ecc) i) * 8) { + ecl = (enum qrcodegen_Ecc) i; + } + } + + // Concatenate all segments to create the data bit string + memset(qrcode, 0, (size_t) qrcodegen_BUFFER_LEN_FOR_VERSION(version) * sizeof(qrcode[0])); + int bitLen = 0; + for (size_t i = 0; i < len; i++) { + const struct qrcodegen_Segment *seg = &segs[i]; + appendBitsToBuffer((unsigned int) seg->mode, 4, qrcode, &bitLen); + appendBitsToBuffer( + (unsigned int) seg->numChars, numCharCountBits(seg->mode, version), qrcode, &bitLen); + for (int j = 0; j < seg->bitLength; j++) { + int bit = (seg->data[j >> 3] >> (7 - (j & 7))) & 1; + appendBitsToBuffer((unsigned int) bit, 1, qrcode, &bitLen); + } + } + assert(bitLen == dataUsedBits); + + // Add terminator and pad up to a byte if applicable + int dataCapacityBits = getNumDataCodewords(version, ecl) * 8; + assert(bitLen <= dataCapacityBits); + int terminatorBits = dataCapacityBits - bitLen; + if (terminatorBits > 4) { + terminatorBits = 4; + } + appendBitsToBuffer(0, terminatorBits, qrcode, &bitLen); + appendBitsToBuffer(0, (8 - bitLen % 8) % 8, qrcode, &bitLen); + assert(bitLen % 8 == 0); + + // Pad with alternating bytes until data capacity is reached + for (uint8_t padByte = 0xEC; bitLen < dataCapacityBits; padByte ^= 0xEC ^ 0x11) { + appendBitsToBuffer(padByte, 8, qrcode, &bitLen); + } + + // Compute ECC, draw modules + addEccAndInterleave(qrcode, version, ecl, tempBuffer); + initializeFunctionModules(version, qrcode); + drawCodewords(tempBuffer, getNumRawDataModules(version) / 8, qrcode); + drawLightFunctionModules(qrcode, version); + initializeFunctionModules(version, tempBuffer); + + // Do masking + if (mask == qrcodegen_Mask_AUTO) { // Automatically choose best mask + long minPenalty = LONG_MAX; + for (int i = 0; i < 8; i++) { + enum qrcodegen_Mask msk = (enum qrcodegen_Mask) i; + applyMask(tempBuffer, qrcode, msk); + drawFormatBits(ecl, msk, qrcode); + long penalty = getPenaltyScore(qrcode); + if (penalty < minPenalty) { + mask = msk; + minPenalty = penalty; + } + applyMask(tempBuffer, qrcode, msk); // Undoes the mask due to XOR + } + } + assert(0 <= (int) mask && (int) mask <= 7); + applyMask(tempBuffer, qrcode, mask); // Apply the final choice of mask + drawFormatBits(ecl, mask, qrcode); // Overwrite old format bits + return true; } - - /*---- Error correction code generation functions ----*/ // Appends error correction bytes to each block of the given data array, then interleaves // bytes from the blocks and stores them in the result array. data[0 : dataLen] contains // the input data. data[dataLen : rawCodewords] is used as a temporary work area and will // be clobbered by this function. The final answer is stored in result[0 : rawCodewords]. -testable void addEccAndInterleave(uint8_t data[], int version, enum qrcodegen_Ecc ecl, uint8_t result[]) { - // Calculate parameter numbers - assert(0 <= (int)ecl && (int)ecl < 4 && qrcodegen_VERSION_MIN <= version && version <= qrcodegen_VERSION_MAX); - int numBlocks = NUM_ERROR_CORRECTION_BLOCKS[(int)ecl][version]; - int blockEccLen = ECC_CODEWORDS_PER_BLOCK [(int)ecl][version]; - int rawCodewords = getNumRawDataModules(version) / 8; - int dataLen = getNumDataCodewords(version, ecl); - int numShortBlocks = numBlocks - rawCodewords % numBlocks; - int shortBlockDataLen = rawCodewords / numBlocks - blockEccLen; - - // Split data into blocks, calculate ECC, and interleave - // (not concatenate) the bytes into a single sequence - uint8_t rsdiv[qrcodegen_REED_SOLOMON_DEGREE_MAX]; - reedSolomonComputeDivisor(blockEccLen, rsdiv); - const uint8_t *dat = data; - for (int i = 0; i < numBlocks; i++) { - int datLen = shortBlockDataLen + (i < numShortBlocks ? 0 : 1); - uint8_t *ecc = &data[dataLen]; // Temporary storage - reedSolomonComputeRemainder(dat, datLen, rsdiv, blockEccLen, ecc); - for (int j = 0, k = i; j < datLen; j++, k += numBlocks) { // Copy data - if (j == shortBlockDataLen) - k -= numShortBlocks; - result[k] = dat[j]; - } - for (int j = 0, k = dataLen + i; j < blockEccLen; j++, k += numBlocks) // Copy ECC - result[k] = ecc[j]; - dat += datLen; - } +testable void addEccAndInterleave(uint8_t data[], + int version, + enum qrcodegen_Ecc ecl, + uint8_t result[]) +{ + // Calculate parameter numbers + assert(0 <= (int) ecl && (int) ecl < 4 && qrcodegen_VERSION_MIN <= version + && version <= qrcodegen_VERSION_MAX); + int numBlocks = NUM_ERROR_CORRECTION_BLOCKS[(int) ecl][version]; + int blockEccLen = ECC_CODEWORDS_PER_BLOCK[(int) ecl][version]; + int rawCodewords = getNumRawDataModules(version) / 8; + int dataLen = getNumDataCodewords(version, ecl); + int numShortBlocks = numBlocks - rawCodewords % numBlocks; + int shortBlockDataLen = rawCodewords / numBlocks - blockEccLen; + + // Split data into blocks, calculate ECC, and interleave + // (not concatenate) the bytes into a single sequence + uint8_t rsdiv[qrcodegen_REED_SOLOMON_DEGREE_MAX]; + reedSolomonComputeDivisor(blockEccLen, rsdiv); + const uint8_t *dat = data; + for (int i = 0; i < numBlocks; i++) { + int datLen = shortBlockDataLen + (i < numShortBlocks ? 0 : 1); + uint8_t *ecc = &data[dataLen]; // Temporary storage + reedSolomonComputeRemainder(dat, datLen, rsdiv, blockEccLen, ecc); + for (int j = 0, k = i; j < datLen; j++, k += numBlocks) { // Copy data + if (j == shortBlockDataLen) { + k -= numShortBlocks; + } + result[k] = dat[j]; + } + for (int j = 0, k = dataLen + i; j < blockEccLen; j++, k += numBlocks) { // Copy ECC + result[k] = ecc[j]; + } + dat += datLen; + } } - // Returns the number of 8-bit codewords that can be used for storing data (not ECC), // for the given version number and error correction level. The result is in the range [9, 2956]. -testable int getNumDataCodewords(int version, enum qrcodegen_Ecc ecl) { - int v = version, e = (int)ecl; - assert(0 <= e && e < 4); - return getNumRawDataModules(v) / 8 - - ECC_CODEWORDS_PER_BLOCK [e][v] - * NUM_ERROR_CORRECTION_BLOCKS[e][v]; +testable int getNumDataCodewords(int version, enum qrcodegen_Ecc ecl) +{ + int v = version, e = (int) ecl; + assert(0 <= e && e < 4); + return getNumRawDataModules(v) / 8 + - ECC_CODEWORDS_PER_BLOCK[e][v] * NUM_ERROR_CORRECTION_BLOCKS[e][v]; } - -// Returns the number of data bits that can be stored in a QR Code of the given version number, after -// all function modules are excluded. This includes remainder bits, so it might not be a multiple of 8. -// The result is in the range [208, 29648]. This could be implemented as a 40-entry lookup table. -testable int getNumRawDataModules(int ver) { - assert(qrcodegen_VERSION_MIN <= ver && ver <= qrcodegen_VERSION_MAX); - int result = (16 * ver + 128) * ver + 64; - if (ver >= 2) { - int numAlign = ver / 7 + 2; - result -= (25 * numAlign - 10) * numAlign - 55; - if (ver >= 7) - result -= 36; - } - assert(208 <= result && result <= 29648); - return result; +// Returns the number of data bits that can be stored in a QR Code of the given version number, +// after all function modules are excluded. This includes remainder bits, so it might not be a +// multiple of 8. The result is in the range [208, 29648]. This could be implemented as a 40-entry +// lookup table. +testable int getNumRawDataModules(int ver) +{ + assert(qrcodegen_VERSION_MIN <= ver && ver <= qrcodegen_VERSION_MAX); + int result = (16 * ver + 128) * ver + 64; + if (ver >= 2) { + int numAlign = ver / 7 + 2; + result -= (25 * numAlign - 10) * numAlign - 55; + if (ver >= 7) { + result -= 36; + } + } + assert(208 <= result && result <= 29648); + return result; } - - /*---- Reed-Solomon ECC generator functions ----*/ -// Computes a Reed-Solomon ECC generator polynomial for the given degree, storing in result[0 : degree]. -// This could be implemented as a lookup table over all possible parameter values, instead of as an algorithm. -testable void reedSolomonComputeDivisor(int degree, uint8_t result[]) { - assert(1 <= degree && degree <= qrcodegen_REED_SOLOMON_DEGREE_MAX); - // Polynomial coefficients are stored from highest to lowest power, excluding the leading term which is always 1. - // For example the polynomial x^3 + 255x^2 + 8x + 93 is stored as the uint8 array {255, 8, 93}. - memset(result, 0, (size_t)degree * sizeof(result[0])); - result[degree - 1] = 1; // Start off with the monomial x^0 - - // Compute the product polynomial (x - r^0) * (x - r^1) * (x - r^2) * ... * (x - r^{degree-1}), - // drop the highest monomial term which is always 1x^degree. - // Note that r = 0x02, which is a generator element of this field GF(2^8/0x11D). - uint8_t root = 1; - for (int i = 0; i < degree; i++) { - // Multiply the current product by (x - r^i) - for (int j = 0; j < degree; j++) { - result[j] = reedSolomonMultiply(result[j], root); - if (j + 1 < degree) - result[j] ^= result[j + 1]; - } - root = reedSolomonMultiply(root, 0x02); - } +// Computes a Reed-Solomon ECC generator polynomial for the given degree, storing in result[0 : +// degree]. This could be implemented as a lookup table over all possible parameter values, instead +// of as an algorithm. +testable void reedSolomonComputeDivisor(int degree, uint8_t result[]) +{ + assert(1 <= degree && degree <= qrcodegen_REED_SOLOMON_DEGREE_MAX); + // Polynomial coefficients are stored from highest to lowest power, excluding the leading term + // which is always 1. For example the polynomial x^3 + 255x^2 + 8x + 93 is stored as the uint8 + // array {255, 8, 93}. + memset(result, 0, (size_t) degree * sizeof(result[0])); + result[degree - 1] = 1; // Start off with the monomial x^0 + + // Compute the product polynomial (x - r^0) * (x - r^1) * (x - r^2) * ... * (x - r^{degree-1}), + // drop the highest monomial term which is always 1x^degree. + // Note that r = 0x02, which is a generator element of this field GF(2^8/0x11D). + uint8_t root = 1; + for (int i = 0; i < degree; i++) { + // Multiply the current product by (x - r^i) + for (int j = 0; j < degree; j++) { + result[j] = reedSolomonMultiply(result[j], root); + if (j + 1 < degree) { + result[j] ^= result[j + 1]; + } + } + root = reedSolomonMultiply(root, 0x02); + } } - // Computes the Reed-Solomon error correction codeword for the given data and divisor polynomials. -// The remainder when data[0 : dataLen] is divided by divisor[0 : degree] is stored in result[0 : degree]. -// All polynomials are in big endian, and the generator has an implicit leading 1 term. -testable void reedSolomonComputeRemainder(const uint8_t data[], int dataLen, - const uint8_t generator[], int degree, uint8_t result[]) { - assert(1 <= degree && degree <= qrcodegen_REED_SOLOMON_DEGREE_MAX); - memset(result, 0, (size_t)degree * sizeof(result[0])); - for (int i = 0; i < dataLen; i++) { // Polynomial division - uint8_t factor = data[i] ^ result[0]; - memmove(&result[0], &result[1], (size_t)(degree - 1) * sizeof(result[0])); - result[degree - 1] = 0; - for (int j = 0; j < degree; j++) - result[j] ^= reedSolomonMultiply(generator[j], factor); - } +// The remainder when data[0 : dataLen] is divided by divisor[0 : degree] is stored in result[0 : +// degree]. All polynomials are in big endian, and the generator has an implicit leading 1 term. +testable void reedSolomonComputeRemainder(const uint8_t data[], + int dataLen, + const uint8_t generator[], + int degree, + uint8_t result[]) +{ + assert(1 <= degree && degree <= qrcodegen_REED_SOLOMON_DEGREE_MAX); + memset(result, 0, (size_t) degree * sizeof(result[0])); + for (int i = 0; i < dataLen; i++) { // Polynomial division + uint8_t factor = data[i] ^ result[0]; + memmove(&result[0], &result[1], (size_t) (degree - 1) * sizeof(result[0])); + result[degree - 1] = 0; + for (int j = 0; j < degree; j++) { + result[j] ^= reedSolomonMultiply(generator[j], factor); + } + } } #undef qrcodegen_REED_SOLOMON_DEGREE_MAX - // Returns the product of the two given field elements modulo GF(2^8/0x11D). // All inputs are valid. This could be implemented as a 256*256 lookup table. -testable uint8_t reedSolomonMultiply(uint8_t x, uint8_t y) { - // Russian peasant multiplication - uint8_t z = 0; - for (int i = 7; i >= 0; i--) { - z = (uint8_t)((z << 1) ^ ((z >> 7) * 0x11D)); - z ^= ((y >> i) & 1) * x; - } - return z; +testable uint8_t reedSolomonMultiply(uint8_t x, uint8_t y) +{ + // Russian peasant multiplication + uint8_t z = 0; + for (int i = 7; i >= 0; i--) { + z = (uint8_t) ((z << 1) ^ ((z >> 7) * 0x11D)); + z ^= ((y >> i) & 1) * x; + } + return z; } - - /*---- Drawing function modules ----*/ // Clears the given QR Code grid with light modules for the given // version's size, then marks every function module as dark. -testable void initializeFunctionModules(int version, uint8_t qrcode[]) { - // Initialize QR Code - int qrsize = version * 4 + 17; - memset(qrcode, 0, (size_t)((qrsize * qrsize + 7) / 8 + 1) * sizeof(qrcode[0])); - qrcode[0] = (uint8_t)qrsize; - - // Fill horizontal and vertical timing patterns - fillRectangle(6, 0, 1, qrsize, qrcode); - fillRectangle(0, 6, qrsize, 1, qrcode); - - // Fill 3 finder patterns (all corners except bottom right) and format bits - fillRectangle(0, 0, 9, 9, qrcode); - fillRectangle(qrsize - 8, 0, 8, 9, qrcode); - fillRectangle(0, qrsize - 8, 9, 8, qrcode); - - // Fill numerous alignment patterns - uint8_t alignPatPos[7]; - int numAlign = getAlignmentPatternPositions(version, alignPatPos); - for (int i = 0; i < numAlign; i++) { - for (int j = 0; j < numAlign; j++) { - // Don't draw on the three finder corners - if (!((i == 0 && j == 0) || (i == 0 && j == numAlign - 1) || (i == numAlign - 1 && j == 0))) - fillRectangle(alignPatPos[i] - 2, alignPatPos[j] - 2, 5, 5, qrcode); - } - } - - // Fill version blocks - if (version >= 7) { - fillRectangle(qrsize - 11, 0, 3, 6, qrcode); - fillRectangle(0, qrsize - 11, 6, 3, qrcode); - } +testable void initializeFunctionModules(int version, uint8_t qrcode[]) +{ + // Initialize QR Code + int qrsize = version * 4 + 17; + memset(qrcode, 0, (size_t) ((qrsize * qrsize + 7) / 8 + 1) * sizeof(qrcode[0])); + qrcode[0] = (uint8_t) qrsize; + + // Fill horizontal and vertical timing patterns + fillRectangle(6, 0, 1, qrsize, qrcode); + fillRectangle(0, 6, qrsize, 1, qrcode); + + // Fill 3 finder patterns (all corners except bottom right) and format bits + fillRectangle(0, 0, 9, 9, qrcode); + fillRectangle(qrsize - 8, 0, 8, 9, qrcode); + fillRectangle(0, qrsize - 8, 9, 8, qrcode); + + // Fill numerous alignment patterns + uint8_t alignPatPos[7]; + int numAlign = getAlignmentPatternPositions(version, alignPatPos); + for (int i = 0; i < numAlign; i++) { + for (int j = 0; j < numAlign; j++) { + // Don't draw on the three finder corners + if (!((i == 0 && j == 0) || (i == 0 && j == numAlign - 1) + || (i == numAlign - 1 && j == 0))) { + fillRectangle(alignPatPos[i] - 2, alignPatPos[j] - 2, 5, 5, qrcode); + } + } + } + + // Fill version blocks + if (version >= 7) { + fillRectangle(qrsize - 11, 0, 3, 6, qrcode); + fillRectangle(0, qrsize - 11, 6, 3, qrcode); + } } - -// Draws light function modules and possibly some dark modules onto the given QR Code, without changing -// non-function modules. This does not draw the format bits. This requires all function modules to be previously -// marked dark (namely by initializeFunctionModules()), because this may skip redrawing dark function modules. -static void drawLightFunctionModules(uint8_t qrcode[], int version) { - // Draw horizontal and vertical timing patterns - int qrsize = qrcodegen_getSize(qrcode); - for (int i = 7; i < qrsize - 7; i += 2) { - setModuleBounded(qrcode, 6, i, false); - setModuleBounded(qrcode, i, 6, false); - } - - // Draw 3 finder patterns (all corners except bottom right; overwrites some timing modules) - for (int dy = -4; dy <= 4; dy++) { - for (int dx = -4; dx <= 4; dx++) { - int dist = abs(dx); - if (abs(dy) > dist) - dist = abs(dy); - if (dist == 2 || dist == 4) { - setModuleUnbounded(qrcode, 3 + dx, 3 + dy, false); - setModuleUnbounded(qrcode, qrsize - 4 + dx, 3 + dy, false); - setModuleUnbounded(qrcode, 3 + dx, qrsize - 4 + dy, false); - } - } - } - - // Draw numerous alignment patterns - uint8_t alignPatPos[7]; - int numAlign = getAlignmentPatternPositions(version, alignPatPos); - for (int i = 0; i < numAlign; i++) { - for (int j = 0; j < numAlign; j++) { - if ((i == 0 && j == 0) || (i == 0 && j == numAlign - 1) || (i == numAlign - 1 && j == 0)) - continue; // Don't draw on the three finder corners - for (int dy = -1; dy <= 1; dy++) { - for (int dx = -1; dx <= 1; dx++) - setModuleBounded(qrcode, alignPatPos[i] + dx, alignPatPos[j] + dy, dx == 0 && dy == 0); - } - } - } - - // Draw version blocks - if (version >= 7) { - // Calculate error correction code and pack bits - int rem = version; // version is uint6, in the range [7, 40] - for (int i = 0; i < 12; i++) - rem = (rem << 1) ^ ((rem >> 11) * 0x1F25); - long bits = (long)version << 12 | rem; // uint18 - assert(bits >> 18 == 0); - - // Draw two copies - for (int i = 0; i < 6; i++) { - for (int j = 0; j < 3; j++) { - int k = qrsize - 11 + j; - setModuleBounded(qrcode, k, i, (bits & 1) != 0); - setModuleBounded(qrcode, i, k, (bits & 1) != 0); - bits >>= 1; - } - } - } +// Draws light function modules and possibly some dark modules onto the given QR Code, without +// changing non-function modules. This does not draw the format bits. This requires all function +// modules to be previously marked dark (namely by initializeFunctionModules()), because this may +// skip redrawing dark function modules. +static void drawLightFunctionModules(uint8_t qrcode[], int version) +{ + // Draw horizontal and vertical timing patterns + int qrsize = qrcodegen_getSize(qrcode); + for (int i = 7; i < qrsize - 7; i += 2) { + setModuleBounded(qrcode, 6, i, false); + setModuleBounded(qrcode, i, 6, false); + } + + // Draw 3 finder patterns (all corners except bottom right; overwrites some timing modules) + for (int dy = -4; dy <= 4; dy++) { + for (int dx = -4; dx <= 4; dx++) { + int dist = abs(dx); + if (abs(dy) > dist) { + dist = abs(dy); + } + if (dist == 2 || dist == 4) { + setModuleUnbounded(qrcode, 3 + dx, 3 + dy, false); + setModuleUnbounded(qrcode, qrsize - 4 + dx, 3 + dy, false); + setModuleUnbounded(qrcode, 3 + dx, qrsize - 4 + dy, false); + } + } + } + + // Draw numerous alignment patterns + uint8_t alignPatPos[7]; + int numAlign = getAlignmentPatternPositions(version, alignPatPos); + for (int i = 0; i < numAlign; i++) { + for (int j = 0; j < numAlign; j++) { + if ((i == 0 && j == 0) || (i == 0 && j == numAlign - 1) + || (i == numAlign - 1 && j == 0)) { + continue; // Don't draw on the three finder corners + } + for (int dy = -1; dy <= 1; dy++) { + for (int dx = -1; dx <= 1; dx++) { + setModuleBounded( + qrcode, alignPatPos[i] + dx, alignPatPos[j] + dy, dx == 0 && dy == 0); + } + } + } + } + + // Draw version blocks + if (version >= 7) { + // Calculate error correction code and pack bits + int rem = version; // version is uint6, in the range [7, 40] + for (int i = 0; i < 12; i++) { + rem = (rem << 1) ^ ((rem >> 11) * 0x1F25); + } + long bits = (long) version << 12 | rem; // uint18 + assert(bits >> 18 == 0); + + // Draw two copies + for (int i = 0; i < 6; i++) { + for (int j = 0; j < 3; j++) { + int k = qrsize - 11 + j; + setModuleBounded(qrcode, k, i, (bits & 1) != 0); + setModuleBounded(qrcode, i, k, (bits & 1) != 0); + bits >>= 1; + } + } + } } - // Draws two copies of the format bits (with its own error correction code) based // on the given mask and error correction level. This always draws all modules of // the format bits, unlike drawLightFunctionModules() which might skip dark modules. -static void drawFormatBits(enum qrcodegen_Ecc ecl, enum qrcodegen_Mask mask, uint8_t qrcode[]) { - // Calculate error correction code and pack bits - assert(0 <= (int)mask && (int)mask <= 7); - static const int table[] = {1, 0, 3, 2}; - int data = table[(int)ecl] << 3 | (int)mask; // errCorrLvl is uint2, mask is uint3 - int rem = data; - for (int i = 0; i < 10; i++) - rem = (rem << 1) ^ ((rem >> 9) * 0x537); - int bits = (data << 10 | rem) ^ 0x5412; // uint15 - assert(bits >> 15 == 0); - - // Draw first copy - for (int i = 0; i <= 5; i++) - setModuleBounded(qrcode, 8, i, getBit(bits, i)); - setModuleBounded(qrcode, 8, 7, getBit(bits, 6)); - setModuleBounded(qrcode, 8, 8, getBit(bits, 7)); - setModuleBounded(qrcode, 7, 8, getBit(bits, 8)); - for (int i = 9; i < 15; i++) - setModuleBounded(qrcode, 14 - i, 8, getBit(bits, i)); - - // Draw second copy - int qrsize = qrcodegen_getSize(qrcode); - for (int i = 0; i < 8; i++) - setModuleBounded(qrcode, qrsize - 1 - i, 8, getBit(bits, i)); - for (int i = 8; i < 15; i++) - setModuleBounded(qrcode, 8, qrsize - 15 + i, getBit(bits, i)); - setModuleBounded(qrcode, 8, qrsize - 8, true); // Always dark +static void drawFormatBits(enum qrcodegen_Ecc ecl, enum qrcodegen_Mask mask, uint8_t qrcode[]) +{ + // Calculate error correction code and pack bits + assert(0 <= (int) mask && (int) mask <= 7); + static const int table[] = {1, 0, 3, 2}; + int data = table[(int) ecl] << 3 | (int) mask; // errCorrLvl is uint2, mask is uint3 + int rem = data; + for (int i = 0; i < 10; i++) { + rem = (rem << 1) ^ ((rem >> 9) * 0x537); + } + int bits = (data << 10 | rem) ^ 0x5412; // uint15 + assert(bits >> 15 == 0); + + // Draw first copy + for (int i = 0; i <= 5; i++) { + setModuleBounded(qrcode, 8, i, getBit(bits, i)); + } + setModuleBounded(qrcode, 8, 7, getBit(bits, 6)); + setModuleBounded(qrcode, 8, 8, getBit(bits, 7)); + setModuleBounded(qrcode, 7, 8, getBit(bits, 8)); + for (int i = 9; i < 15; i++) { + setModuleBounded(qrcode, 14 - i, 8, getBit(bits, i)); + } + + // Draw second copy + int qrsize = qrcodegen_getSize(qrcode); + for (int i = 0; i < 8; i++) { + setModuleBounded(qrcode, qrsize - 1 - i, 8, getBit(bits, i)); + } + for (int i = 8; i < 15; i++) { + setModuleBounded(qrcode, 8, qrsize - 15 + i, getBit(bits, i)); + } + setModuleBounded(qrcode, 8, qrsize - 8, true); // Always dark } - // Calculates and stores an ascending list of positions of alignment patterns // for this version number, returning the length of the list (in the range [0,7]). // Each position is in the range [0,177), and are used on both the x and y axes. // This could be implemented as lookup table of 40 variable-length lists of unsigned bytes. -testable int getAlignmentPatternPositions(int version, uint8_t result[7]) { - if (version == 1) - return 0; - int numAlign = version / 7 + 2; - int step = (version == 32) ? 26 : - (version * 4 + numAlign * 2 + 1) / (numAlign * 2 - 2) * 2; - for (int i = numAlign - 1, pos = version * 4 + 10; i >= 1; i--, pos -= step) - result[i] = (uint8_t)pos; - result[0] = 6; - return numAlign; +testable int getAlignmentPatternPositions(int version, uint8_t result[7]) +{ + if (version == 1) { + return 0; + } + int numAlign = version / 7 + 2; + int step = (version == 32) ? 26 : (version * 4 + numAlign * 2 + 1) / (numAlign * 2 - 2) * 2; + for (int i = numAlign - 1, pos = version * 4 + 10; i >= 1; i--, pos -= step) { + result[i] = (uint8_t) pos; + } + result[0] = 6; + return numAlign; } - // Sets every module in the range [left : left + width] * [top : top + height] to dark. -static void fillRectangle(int left, int top, int width, int height, uint8_t qrcode[]) { - for (int dy = 0; dy < height; dy++) { - for (int dx = 0; dx < width; dx++) - setModuleBounded(qrcode, left + dx, top + dy, true); - } +static void fillRectangle(int left, int top, int width, int height, uint8_t qrcode[]) +{ + for (int dy = 0; dy < height; dy++) { + for (int dx = 0; dx < width; dx++) { + setModuleBounded(qrcode, left + dx, top + dy, true); + } + } } - - /*---- Drawing data modules and masking ----*/ -// Draws the raw codewords (including data and ECC) onto the given QR Code. This requires the initial state of -// the QR Code to be dark at function modules and light at codeword modules (including unused remainder bits). -static void drawCodewords(const uint8_t data[], int dataLen, uint8_t qrcode[]) { - int qrsize = qrcodegen_getSize(qrcode); - int i = 0; // Bit index into the data - // Do the funny zigzag scan - for (int right = qrsize - 1; right >= 1; right -= 2) { // Index of right column in each column pair - if (right == 6) - right = 5; - for (int vert = 0; vert < qrsize; vert++) { // Vertical counter - for (int j = 0; j < 2; j++) { - int x = right - j; // Actual x coordinate - bool upward = ((right + 1) & 2) == 0; - int y = upward ? qrsize - 1 - vert : vert; // Actual y coordinate - if (!getModuleBounded(qrcode, x, y) && i < dataLen * 8) { - bool dark = getBit(data[i >> 3], 7 - (i & 7)); - setModuleBounded(qrcode, x, y, dark); - i++; - } - // If this QR Code has any remainder bits (0 to 7), they were assigned as - // 0/false/light by the constructor and are left unchanged by this method - } - } - } - assert(i == dataLen * 8); +// Draws the raw codewords (including data and ECC) onto the given QR Code. This requires the +// initial state of the QR Code to be dark at function modules and light at codeword modules +// (including unused remainder bits). +static void drawCodewords(const uint8_t data[], int dataLen, uint8_t qrcode[]) +{ + int qrsize = qrcodegen_getSize(qrcode); + int i = 0; // Bit index into the data + // Do the funny zigzag scan + for (int right = qrsize - 1; right >= 1; + right -= 2) { // Index of right column in each column pair + if (right == 6) { + right = 5; + } + for (int vert = 0; vert < qrsize; vert++) { // Vertical counter + for (int j = 0; j < 2; j++) { + int x = right - j; // Actual x coordinate + bool upward = ((right + 1) & 2) == 0; + int y = upward ? qrsize - 1 - vert : vert; // Actual y coordinate + if (!getModuleBounded(qrcode, x, y) && i < dataLen * 8) { + bool dark = getBit(data[i >> 3], 7 - (i & 7)); + setModuleBounded(qrcode, x, y, dark); + i++; + } + // If this QR Code has any remainder bits (0 to 7), they were assigned as + // 0/false/light by the constructor and are left unchanged by this method + } + } + } + assert(i == dataLen * 8); } - // XORs the codeword modules in this QR Code with the given mask pattern // and given pattern of function modules. The codeword bits must be drawn // before masking. Due to the arithmetic of XOR, calling applyMask() with // the same mask value a second time will undo the mask. A final well-formed // QR Code needs exactly one (not zero, two, etc.) mask applied. -static void applyMask(const uint8_t functionModules[], uint8_t qrcode[], enum qrcodegen_Mask mask) { - assert(0 <= (int)mask && (int)mask <= 7); // Disallows qrcodegen_Mask_AUTO - int qrsize = qrcodegen_getSize(qrcode); - for (int y = 0; y < qrsize; y++) { - for (int x = 0; x < qrsize; x++) { - if (getModuleBounded(functionModules, x, y)) - continue; - bool invert; - switch ((int)mask) { - case 0: invert = (x + y) % 2 == 0; break; - case 1: invert = y % 2 == 0; break; - case 2: invert = x % 3 == 0; break; - case 3: invert = (x + y) % 3 == 0; break; - case 4: invert = (x / 3 + y / 2) % 2 == 0; break; - case 5: invert = x * y % 2 + x * y % 3 == 0; break; - case 6: invert = (x * y % 2 + x * y % 3) % 2 == 0; break; - case 7: invert = ((x + y) % 2 + x * y % 3) % 2 == 0; break; - default: assert(false); return; - } - bool val = getModuleBounded(qrcode, x, y); - setModuleBounded(qrcode, x, y, val ^ invert); - } - } +static void applyMask(const uint8_t functionModules[], uint8_t qrcode[], enum qrcodegen_Mask mask) +{ + assert(0 <= (int) mask && (int) mask <= 7); // Disallows qrcodegen_Mask_AUTO + int qrsize = qrcodegen_getSize(qrcode); + for (int y = 0; y < qrsize; y++) { + for (int x = 0; x < qrsize; x++) { + if (getModuleBounded(functionModules, x, y)) { + continue; + } + bool invert; + switch ((int) mask) { + case 0: + invert = (x + y) % 2 == 0; + break; + case 1: + invert = y % 2 == 0; + break; + case 2: + invert = x % 3 == 0; + break; + case 3: + invert = (x + y) % 3 == 0; + break; + case 4: + invert = (x / 3 + y / 2) % 2 == 0; + break; + case 5: + invert = x * y % 2 + x * y % 3 == 0; + break; + case 6: + invert = (x * y % 2 + x * y % 3) % 2 == 0; + break; + case 7: + invert = ((x + y) % 2 + x * y % 3) % 2 == 0; + break; + default: + assert(false); + return; + } + bool val = getModuleBounded(qrcode, x, y); + setModuleBounded(qrcode, x, y, val ^ invert); + } + } } - // Calculates and returns the penalty score based on state of the given QR Code's current modules. -// This is used by the automatic mask choice algorithm to find the mask pattern that yields the lowest score. -static long getPenaltyScore(const uint8_t qrcode[]) { - int qrsize = qrcodegen_getSize(qrcode); - long result = 0; - - // Adjacent modules in row having same color, and finder-like patterns - for (int y = 0; y < qrsize; y++) { - bool runColor = false; - int runX = 0; - int runHistory[7] = {0}; - for (int x = 0; x < qrsize; x++) { - if (getModuleBounded(qrcode, x, y) == runColor) { - runX++; - if (runX == 5) - result += PENALTY_N1; - else if (runX > 5) - result++; - } else { - finderPenaltyAddHistory(runX, runHistory, qrsize); - if (!runColor) - result += finderPenaltyCountPatterns(runHistory, qrsize) * PENALTY_N3; - runColor = getModuleBounded(qrcode, x, y); - runX = 1; - } - } - result += finderPenaltyTerminateAndCount(runColor, runX, runHistory, qrsize) * PENALTY_N3; - } - // Adjacent modules in column having same color, and finder-like patterns - for (int x = 0; x < qrsize; x++) { - bool runColor = false; - int runY = 0; - int runHistory[7] = {0}; - for (int y = 0; y < qrsize; y++) { - if (getModuleBounded(qrcode, x, y) == runColor) { - runY++; - if (runY == 5) - result += PENALTY_N1; - else if (runY > 5) - result++; - } else { - finderPenaltyAddHistory(runY, runHistory, qrsize); - if (!runColor) - result += finderPenaltyCountPatterns(runHistory, qrsize) * PENALTY_N3; - runColor = getModuleBounded(qrcode, x, y); - runY = 1; - } - } - result += finderPenaltyTerminateAndCount(runColor, runY, runHistory, qrsize) * PENALTY_N3; - } - - // 2*2 blocks of modules having same color - for (int y = 0; y < qrsize - 1; y++) { - for (int x = 0; x < qrsize - 1; x++) { - bool color = getModuleBounded(qrcode, x, y); - if ( color == getModuleBounded(qrcode, x + 1, y) && - color == getModuleBounded(qrcode, x, y + 1) && - color == getModuleBounded(qrcode, x + 1, y + 1)) - result += PENALTY_N2; - } - } - - // Balance of dark and light modules - int dark = 0; - for (int y = 0; y < qrsize; y++) { - for (int x = 0; x < qrsize; x++) { - if (getModuleBounded(qrcode, x, y)) - dark++; - } - } - int total = qrsize * qrsize; // Note that size is odd, so dark/total != 1/2 - // Compute the smallest integer k >= 0 such that (45-5k)% <= dark/total <= (55+5k)% - int k = (int)((labs(dark * 20L - total * 10L) + total - 1) / total) - 1; - assert(0 <= k && k <= 9); - result += k * PENALTY_N4; - assert(0 <= result && result <= 2568888L); // Non-tight upper bound based on default values of PENALTY_N1, ..., N4 - return result; +// This is used by the automatic mask choice algorithm to find the mask pattern that yields the +// lowest score. +static long getPenaltyScore(const uint8_t qrcode[]) +{ + int qrsize = qrcodegen_getSize(qrcode); + long result = 0; + + // Adjacent modules in row having same color, and finder-like patterns + for (int y = 0; y < qrsize; y++) { + bool runColor = false; + int runX = 0; + int runHistory[7] = {0}; + for (int x = 0; x < qrsize; x++) { + if (getModuleBounded(qrcode, x, y) == runColor) { + runX++; + if (runX == 5) { + result += PENALTY_N1; + } + else if (runX > 5) { + result++; + } + } + else { + finderPenaltyAddHistory(runX, runHistory, qrsize); + if (!runColor) { + result += finderPenaltyCountPatterns(runHistory, qrsize) * PENALTY_N3; + } + runColor = getModuleBounded(qrcode, x, y); + runX = 1; + } + } + result += finderPenaltyTerminateAndCount(runColor, runX, runHistory, qrsize) * PENALTY_N3; + } + // Adjacent modules in column having same color, and finder-like patterns + for (int x = 0; x < qrsize; x++) { + bool runColor = false; + int runY = 0; + int runHistory[7] = {0}; + for (int y = 0; y < qrsize; y++) { + if (getModuleBounded(qrcode, x, y) == runColor) { + runY++; + if (runY == 5) { + result += PENALTY_N1; + } + else if (runY > 5) { + result++; + } + } + else { + finderPenaltyAddHistory(runY, runHistory, qrsize); + if (!runColor) { + result += finderPenaltyCountPatterns(runHistory, qrsize) * PENALTY_N3; + } + runColor = getModuleBounded(qrcode, x, y); + runY = 1; + } + } + result += finderPenaltyTerminateAndCount(runColor, runY, runHistory, qrsize) * PENALTY_N3; + } + + // 2*2 blocks of modules having same color + for (int y = 0; y < qrsize - 1; y++) { + for (int x = 0; x < qrsize - 1; x++) { + bool color = getModuleBounded(qrcode, x, y); + if (color == getModuleBounded(qrcode, x + 1, y) + && color == getModuleBounded(qrcode, x, y + 1) + && color == getModuleBounded(qrcode, x + 1, y + 1)) { + result += PENALTY_N2; + } + } + } + + // Balance of dark and light modules + int dark = 0; + for (int y = 0; y < qrsize; y++) { + for (int x = 0; x < qrsize; x++) { + if (getModuleBounded(qrcode, x, y)) { + dark++; + } + } + } + int total = qrsize * qrsize; // Note that size is odd, so dark/total != 1/2 + // Compute the smallest integer k >= 0 such that (45-5k)% <= dark/total <= (55+5k)% + int k = (int) ((labs(dark * 20L - total * 10L) + total - 1) / total) - 1; + assert(0 <= k && k <= 9); + result += k * PENALTY_N4; + assert(0 <= result && result <= 2568888L); // Non-tight upper bound based on default values of + // PENALTY_N1, ..., N4 + return result; } - // Can only be called immediately after a light run is added, and // returns either 0, 1, or 2. A helper function for getPenaltyScore(). -static int finderPenaltyCountPatterns(const int runHistory[7], int qrsize) { - int n = runHistory[1]; - assert(n <= qrsize * 3); (void)qrsize; - bool core = n > 0 && runHistory[2] == n && runHistory[3] == n * 3 && runHistory[4] == n && runHistory[5] == n; - // The maximum QR Code size is 177, hence the dark run length n <= 177. - // Arithmetic is promoted to int, so n*4 will not overflow. - return (core && runHistory[0] >= n * 4 && runHistory[6] >= n ? 1 : 0) - + (core && runHistory[6] >= n * 4 && runHistory[0] >= n ? 1 : 0); +static int finderPenaltyCountPatterns(const int runHistory[7], int qrsize) +{ + int n = runHistory[1]; + assert(n <= qrsize * 3); + (void) qrsize; + bool core = n > 0 && runHistory[2] == n && runHistory[3] == n * 3 && runHistory[4] == n + && runHistory[5] == n; + // The maximum QR Code size is 177, hence the dark run length n <= 177. + // Arithmetic is promoted to int, so n*4 will not overflow. + return (core && runHistory[0] >= n * 4 && runHistory[6] >= n ? 1 : 0) + + (core && runHistory[6] >= n * 4 && runHistory[0] >= n ? 1 : 0); } - -// Must be called at the end of a line (row or column) of modules. A helper function for getPenaltyScore(). -static int finderPenaltyTerminateAndCount(bool currentRunColor, int currentRunLength, int runHistory[7], int qrsize) { - if (currentRunColor) { // Terminate dark run - finderPenaltyAddHistory(currentRunLength, runHistory, qrsize); - currentRunLength = 0; - } - currentRunLength += qrsize; // Add light border to final run - finderPenaltyAddHistory(currentRunLength, runHistory, qrsize); - return finderPenaltyCountPatterns(runHistory, qrsize); +// Must be called at the end of a line (row or column) of modules. A helper function for +// getPenaltyScore(). +static int finderPenaltyTerminateAndCount(bool currentRunColor, + int currentRunLength, + int runHistory[7], + int qrsize) +{ + if (currentRunColor) { // Terminate dark run + finderPenaltyAddHistory(currentRunLength, runHistory, qrsize); + currentRunLength = 0; + } + currentRunLength += qrsize; // Add light border to final run + finderPenaltyAddHistory(currentRunLength, runHistory, qrsize); + return finderPenaltyCountPatterns(runHistory, qrsize); } - -// Pushes the given value to the front and drops the last value. A helper function for getPenaltyScore(). -static void finderPenaltyAddHistory(int currentRunLength, int runHistory[7], int qrsize) { - if (runHistory[0] == 0) - currentRunLength += qrsize; // Add light border to initial run - memmove(&runHistory[1], &runHistory[0], 6 * sizeof(runHistory[0])); - runHistory[0] = currentRunLength; +// Pushes the given value to the front and drops the last value. A helper function for +// getPenaltyScore(). +static void finderPenaltyAddHistory(int currentRunLength, int runHistory[7], int qrsize) +{ + if (runHistory[0] == 0) { + currentRunLength += qrsize; // Add light border to initial run + } + memmove(&runHistory[1], &runHistory[0], 6 * sizeof(runHistory[0])); + runHistory[0] = currentRunLength; } - - /*---- Basic QR Code information ----*/ // Public function - see documentation comment in header file. -int qrcodegen_getSize(const uint8_t qrcode[]) { - assert(qrcode != NULL); - int result = qrcode[0]; - assert((qrcodegen_VERSION_MIN * 4 + 17) <= result - && result <= (qrcodegen_VERSION_MAX * 4 + 17)); - return result; +int qrcodegen_getSize(const uint8_t qrcode[]) +{ + assert(qrcode != NULL); + int result = qrcode[0]; + assert((qrcodegen_VERSION_MIN * 4 + 17) <= result + && result <= (qrcodegen_VERSION_MAX * 4 + 17)); + return result; } - // Public function - see documentation comment in header file. -bool qrcodegen_getModule(const uint8_t qrcode[], int x, int y) { - assert(qrcode != NULL); - int qrsize = qrcode[0]; - return (0 <= x && x < qrsize && 0 <= y && y < qrsize) && getModuleBounded(qrcode, x, y); +bool qrcodegen_getModule(const uint8_t qrcode[], int x, int y) +{ + assert(qrcode != NULL); + int qrsize = qrcode[0]; + return (0 <= x && x < qrsize && 0 <= y && y < qrsize) && getModuleBounded(qrcode, x, y); } - // Returns the color of the module at the given coordinates, which must be in bounds. -testable bool getModuleBounded(const uint8_t qrcode[], int x, int y) { - int qrsize = qrcode[0]; - assert(21 <= qrsize && qrsize <= 177 && 0 <= x && x < qrsize && 0 <= y && y < qrsize); - int index = y * qrsize + x; - return getBit(qrcode[(index >> 3) + 1], index & 7); +testable bool getModuleBounded(const uint8_t qrcode[], int x, int y) +{ + int qrsize = qrcode[0]; + assert(21 <= qrsize && qrsize <= 177 && 0 <= x && x < qrsize && 0 <= y && y < qrsize); + int index = y * qrsize + x; + return getBit(qrcode[(index >> 3) + 1], index & 7); } - // Sets the color of the module at the given coordinates, which must be in bounds. -testable void setModuleBounded(uint8_t qrcode[], int x, int y, bool isDark) { - int qrsize = qrcode[0]; - assert(21 <= qrsize && qrsize <= 177 && 0 <= x && x < qrsize && 0 <= y && y < qrsize); - int index = y * qrsize + x; - int bitIndex = index & 7; - int byteIndex = (index >> 3) + 1; - if (isDark) - qrcode[byteIndex] |= 1 << bitIndex; - else - qrcode[byteIndex] &= (1 << bitIndex) ^ 0xFF; +testable void setModuleBounded(uint8_t qrcode[], int x, int y, bool isDark) +{ + int qrsize = qrcode[0]; + assert(21 <= qrsize && qrsize <= 177 && 0 <= x && x < qrsize && 0 <= y && y < qrsize); + int index = y * qrsize + x; + int bitIndex = index & 7; + int byteIndex = (index >> 3) + 1; + if (isDark) { + qrcode[byteIndex] |= 1 << bitIndex; + } + else { + qrcode[byteIndex] &= (1 << bitIndex) ^ 0xFF; + } } - // Sets the color of the module at the given coordinates, doing nothing if out of bounds. -testable void setModuleUnbounded(uint8_t qrcode[], int x, int y, bool isDark) { - int qrsize = qrcode[0]; - if (0 <= x && x < qrsize && 0 <= y && y < qrsize) - setModuleBounded(qrcode, x, y, isDark); +testable void setModuleUnbounded(uint8_t qrcode[], int x, int y, bool isDark) +{ + int qrsize = qrcode[0]; + if (0 <= x && x < qrsize && 0 <= y && y < qrsize) { + setModuleBounded(qrcode, x, y, isDark); + } } - // Returns true iff the i'th bit of x is set to 1. Requires x >= 0 and 0 <= i <= 14. -static bool getBit(int x, int i) { - return ((x >> i) & 1) != 0; +static bool getBit(int x, int i) +{ + return ((x >> i) & 1) != 0; } - - /*---- Segment handling ----*/ // Public function - see documentation comment in header file. -bool qrcodegen_isNumeric(const char *text) { - assert(text != NULL); - for (; *text != '\0'; text++) { - if (*text < '0' || *text > '9') - return false; - } - return true; +bool qrcodegen_isNumeric(const char *text) +{ + assert(text != NULL); + for (; *text != '\0'; text++) { + if (*text < '0' || *text > '9') { + return false; + } + } + return true; } - // Public function - see documentation comment in header file. -bool qrcodegen_isAlphanumeric(const char *text) { - assert(text != NULL); - for (; *text != '\0'; text++) { - if (strchr(ALPHANUMERIC_CHARSET, *text) == NULL) - return false; - } - return true; +bool qrcodegen_isAlphanumeric(const char *text) +{ + assert(text != NULL); + for (; *text != '\0'; text++) { + if (strchr(ALPHANUMERIC_CHARSET, *text) == NULL) { + return false; + } + } + return true; } - // Public function - see documentation comment in header file. -size_t qrcodegen_calcSegmentBufferSize(enum qrcodegen_Mode mode, size_t numChars) { - int temp = calcSegmentBitLength(mode, numChars); - if (temp == -1) - return SIZE_MAX; - assert(0 <= temp && temp <= INT16_MAX); - return ((size_t)temp + 7) / 8; +size_t qrcodegen_calcSegmentBufferSize(enum qrcodegen_Mode mode, size_t numChars) +{ + int temp = calcSegmentBitLength(mode, numChars); + if (temp == -1) { + return SIZE_MAX; + } + assert(0 <= temp && temp <= INT16_MAX); + return ((size_t) temp + 7) / 8; } - // Returns the number of data bits needed to represent a segment // containing the given number of characters using the given mode. Notes: // - Returns -1 on failure, i.e. numChars > INT16_MAX or @@ -850,177 +986,212 @@ size_t qrcodegen_calcSegmentBufferSize(enum qrcodegen_Mode mode, size_t numChars // - For byte mode, numChars measures the number of bytes, not Unicode code points. // - For ECI mode, numChars must be 0, and the worst-case number of bits is returned. // An actual ECI segment can have shorter data. For non-ECI modes, the result is exact. -testable int calcSegmentBitLength(enum qrcodegen_Mode mode, size_t numChars) { - // All calculations are designed to avoid overflow on all platforms - if (numChars > (unsigned int)INT16_MAX) - return -1; - long result = (long)numChars; - if (mode == qrcodegen_Mode_NUMERIC) - result = (result * 10 + 2) / 3; // ceil(10/3 * n) - else if (mode == qrcodegen_Mode_ALPHANUMERIC) - result = (result * 11 + 1) / 2; // ceil(11/2 * n) - else if (mode == qrcodegen_Mode_BYTE) - result *= 8; - else if (mode == qrcodegen_Mode_KANJI) - result *= 13; - else if (mode == qrcodegen_Mode_ECI && numChars == 0) - result = 3 * 8; - else { // Invalid argument - assert(false); - return -1; - } - assert(result >= 0); - if (result > INT16_MAX) - return -1; - return (int)result; +testable int calcSegmentBitLength(enum qrcodegen_Mode mode, size_t numChars) +{ + // All calculations are designed to avoid overflow on all platforms + if (numChars > (unsigned int) INT16_MAX) { + return -1; + } + long result = (long) numChars; + if (mode == qrcodegen_Mode_NUMERIC) { + result = (result * 10 + 2) / 3; // ceil(10/3 * n) + } + else if (mode == qrcodegen_Mode_ALPHANUMERIC) { + result = (result * 11 + 1) / 2; // ceil(11/2 * n) + } + else if (mode == qrcodegen_Mode_BYTE) { + result *= 8; + } + else if (mode == qrcodegen_Mode_KANJI) { + result *= 13; + } + else if (mode == qrcodegen_Mode_ECI && numChars == 0) { + result = 3 * 8; + } + else { // Invalid argument + assert(false); + return -1; + } + assert(result >= 0); + if (result > INT16_MAX) { + return -1; + } + return (int) result; } - // Public function - see documentation comment in header file. -struct qrcodegen_Segment qrcodegen_makeBytes(const uint8_t data[], size_t len, uint8_t buf[]) { - assert(data != NULL || len == 0); - struct qrcodegen_Segment result; - result.mode = qrcodegen_Mode_BYTE; - result.bitLength = calcSegmentBitLength(result.mode, len); - assert(result.bitLength != -1); - result.numChars = (int)len; - if (len > 0) - memcpy(buf, data, len * sizeof(buf[0])); - result.data = buf; - return result; +struct qrcodegen_Segment qrcodegen_makeBytes(const uint8_t data[], size_t len, uint8_t buf[]) +{ + assert(data != NULL || len == 0); + struct qrcodegen_Segment result; + result.mode = qrcodegen_Mode_BYTE; + result.bitLength = calcSegmentBitLength(result.mode, len); + assert(result.bitLength != -1); + result.numChars = (int) len; + if (len > 0) { + memcpy(buf, data, len * sizeof(buf[0])); + } + result.data = buf; + return result; } - // Public function - see documentation comment in header file. -struct qrcodegen_Segment qrcodegen_makeNumeric(const char *digits, uint8_t buf[]) { - assert(digits != NULL); - struct qrcodegen_Segment result; - size_t len = strlen(digits); - result.mode = qrcodegen_Mode_NUMERIC; - int bitLen = calcSegmentBitLength(result.mode, len); - assert(bitLen != -1); - result.numChars = (int)len; - if (bitLen > 0) - memset(buf, 0, ((size_t)bitLen + 7) / 8 * sizeof(buf[0])); - result.bitLength = 0; - - unsigned int accumData = 0; - int accumCount = 0; - for (; *digits != '\0'; digits++) { - char c = *digits; - assert('0' <= c && c <= '9'); - accumData = accumData * 10 + (unsigned int)(c - '0'); - accumCount++; - if (accumCount == 3) { - appendBitsToBuffer(accumData, 10, buf, &result.bitLength); - accumData = 0; - accumCount = 0; - } - } - if (accumCount > 0) // 1 or 2 digits remaining - appendBitsToBuffer(accumData, accumCount * 3 + 1, buf, &result.bitLength); - assert(result.bitLength == bitLen); - result.data = buf; - return result; +struct qrcodegen_Segment qrcodegen_makeNumeric(const char *digits, uint8_t buf[]) +{ + assert(digits != NULL); + struct qrcodegen_Segment result; + size_t len = strlen(digits); + result.mode = qrcodegen_Mode_NUMERIC; + int bitLen = calcSegmentBitLength(result.mode, len); + assert(bitLen != -1); + result.numChars = (int) len; + if (bitLen > 0) { + memset(buf, 0, ((size_t) bitLen + 7) / 8 * sizeof(buf[0])); + } + result.bitLength = 0; + + unsigned int accumData = 0; + int accumCount = 0; + for (; *digits != '\0'; digits++) { + char c = *digits; + assert('0' <= c && c <= '9'); + accumData = accumData * 10 + (unsigned int) (c - '0'); + accumCount++; + if (accumCount == 3) { + appendBitsToBuffer(accumData, 10, buf, &result.bitLength); + accumData = 0; + accumCount = 0; + } + } + if (accumCount > 0) { // 1 or 2 digits remaining + appendBitsToBuffer(accumData, accumCount * 3 + 1, buf, &result.bitLength); + } + assert(result.bitLength == bitLen); + result.data = buf; + return result; } - // Public function - see documentation comment in header file. -struct qrcodegen_Segment qrcodegen_makeAlphanumeric(const char *text, uint8_t buf[]) { - assert(text != NULL); - struct qrcodegen_Segment result; - size_t len = strlen(text); - result.mode = qrcodegen_Mode_ALPHANUMERIC; - int bitLen = calcSegmentBitLength(result.mode, len); - assert(bitLen != -1); - result.numChars = (int)len; - if (bitLen > 0) - memset(buf, 0, ((size_t)bitLen + 7) / 8 * sizeof(buf[0])); - result.bitLength = 0; - - unsigned int accumData = 0; - int accumCount = 0; - for (; *text != '\0'; text++) { - const char *temp = strchr(ALPHANUMERIC_CHARSET, *text); - assert(temp != NULL); - accumData = accumData * 45 + (unsigned int)(temp - ALPHANUMERIC_CHARSET); - accumCount++; - if (accumCount == 2) { - appendBitsToBuffer(accumData, 11, buf, &result.bitLength); - accumData = 0; - accumCount = 0; - } - } - if (accumCount > 0) // 1 character remaining - appendBitsToBuffer(accumData, 6, buf, &result.bitLength); - assert(result.bitLength == bitLen); - result.data = buf; - return result; +struct qrcodegen_Segment qrcodegen_makeAlphanumeric(const char *text, uint8_t buf[]) +{ + assert(text != NULL); + struct qrcodegen_Segment result; + size_t len = strlen(text); + result.mode = qrcodegen_Mode_ALPHANUMERIC; + int bitLen = calcSegmentBitLength(result.mode, len); + assert(bitLen != -1); + result.numChars = (int) len; + if (bitLen > 0) { + memset(buf, 0, ((size_t) bitLen + 7) / 8 * sizeof(buf[0])); + } + result.bitLength = 0; + + unsigned int accumData = 0; + int accumCount = 0; + for (; *text != '\0'; text++) { + const char *temp = strchr(ALPHANUMERIC_CHARSET, *text); + assert(temp != NULL); + accumData = accumData * 45 + (unsigned int) (temp - ALPHANUMERIC_CHARSET); + accumCount++; + if (accumCount == 2) { + appendBitsToBuffer(accumData, 11, buf, &result.bitLength); + accumData = 0; + accumCount = 0; + } + } + if (accumCount > 0) { // 1 character remaining + appendBitsToBuffer(accumData, 6, buf, &result.bitLength); + } + assert(result.bitLength == bitLen); + result.data = buf; + return result; } - // Public function - see documentation comment in header file. -struct qrcodegen_Segment qrcodegen_makeEci(long assignVal, uint8_t buf[]) { - struct qrcodegen_Segment result; - result.mode = qrcodegen_Mode_ECI; - result.numChars = 0; - result.bitLength = 0; - if (assignVal < 0) { - assert(false); - } else if (assignVal < (1 << 7)) { - memset(buf, 0, 1 * sizeof(buf[0])); - appendBitsToBuffer((unsigned int)assignVal, 8, buf, &result.bitLength); - } else if (assignVal < (1 << 14)) { - memset(buf, 0, 2 * sizeof(buf[0])); - appendBitsToBuffer(2, 2, buf, &result.bitLength); - appendBitsToBuffer((unsigned int)assignVal, 14, buf, &result.bitLength); - } else if (assignVal < 1000000L) { - memset(buf, 0, 3 * sizeof(buf[0])); - appendBitsToBuffer(6, 3, buf, &result.bitLength); - appendBitsToBuffer((unsigned int)(assignVal >> 10), 11, buf, &result.bitLength); - appendBitsToBuffer((unsigned int)(assignVal & 0x3FF), 10, buf, &result.bitLength); - } else - assert(false); - result.data = buf; - return result; +struct qrcodegen_Segment qrcodegen_makeEci(long assignVal, uint8_t buf[]) +{ + struct qrcodegen_Segment result; + result.mode = qrcodegen_Mode_ECI; + result.numChars = 0; + result.bitLength = 0; + if (assignVal < 0) { + assert(false); + } + else if (assignVal < (1 << 7)) { + memset(buf, 0, 1 * sizeof(buf[0])); + appendBitsToBuffer((unsigned int) assignVal, 8, buf, &result.bitLength); + } + else if (assignVal < (1 << 14)) { + memset(buf, 0, 2 * sizeof(buf[0])); + appendBitsToBuffer(2, 2, buf, &result.bitLength); + appendBitsToBuffer((unsigned int) assignVal, 14, buf, &result.bitLength); + } + else if (assignVal < 1000000L) { + memset(buf, 0, 3 * sizeof(buf[0])); + appendBitsToBuffer(6, 3, buf, &result.bitLength); + appendBitsToBuffer((unsigned int) (assignVal >> 10), 11, buf, &result.bitLength); + appendBitsToBuffer((unsigned int) (assignVal & 0x3FF), 10, buf, &result.bitLength); + } + else { + assert(false); + } + result.data = buf; + return result; } - // Calculates the number of bits needed to encode the given segments at the given version. // Returns a non-negative number if successful. Otherwise returns -1 if a segment has too // many characters to fit its length field, or the total bits exceeds INT16_MAX. -testable int getTotalBits(const struct qrcodegen_Segment segs[], size_t len, int version) { - assert(segs != NULL || len == 0); - long result = 0; - for (size_t i = 0; i < len; i++) { - int numChars = segs[i].numChars; - int bitLength = segs[i].bitLength; - assert(0 <= numChars && numChars <= INT16_MAX); - assert(0 <= bitLength && bitLength <= INT16_MAX); - int ccbits = numCharCountBits(segs[i].mode, version); - assert(0 <= ccbits && ccbits <= 16); - if (numChars >= (1L << ccbits)) - return -1; // The segment's length doesn't fit the field's bit width - result += 4L + ccbits + bitLength; - if (result > INT16_MAX) - return -1; // The sum might overflow an int type - } - assert(0 <= result && result <= INT16_MAX); - return (int)result; +testable int getTotalBits(const struct qrcodegen_Segment segs[], size_t len, int version) +{ + assert(segs != NULL || len == 0); + long result = 0; + for (size_t i = 0; i < len; i++) { + int numChars = segs[i].numChars; + int bitLength = segs[i].bitLength; + assert(0 <= numChars && numChars <= INT16_MAX); + assert(0 <= bitLength && bitLength <= INT16_MAX); + int ccbits = numCharCountBits(segs[i].mode, version); + assert(0 <= ccbits && ccbits <= 16); + if (numChars >= (1L << ccbits)) { + return -1; // The segment's length doesn't fit the field's bit width + } + result += 4L + ccbits + bitLength; + if (result > INT16_MAX) { + return -1; // The sum might overflow an int type + } + } + assert(0 <= result && result <= INT16_MAX); + return (int) result; } - // Returns the bit width of the character count field for a segment in the given mode // in a QR Code at the given version number. The result is in the range [0, 16]. -static int numCharCountBits(enum qrcodegen_Mode mode, int version) { - assert(qrcodegen_VERSION_MIN <= version && version <= qrcodegen_VERSION_MAX); - int i = (version + 7) / 17; - switch (mode) { - case qrcodegen_Mode_NUMERIC : { static const int temp[] = {10, 12, 14}; return temp[i]; } - case qrcodegen_Mode_ALPHANUMERIC: { static const int temp[] = { 9, 11, 13}; return temp[i]; } - case qrcodegen_Mode_BYTE : { static const int temp[] = { 8, 16, 16}; return temp[i]; } - case qrcodegen_Mode_KANJI : { static const int temp[] = { 8, 10, 12}; return temp[i]; } - case qrcodegen_Mode_ECI : return 0; - default: assert(false); return -1; // Dummy value - } +static int numCharCountBits(enum qrcodegen_Mode mode, int version) +{ + assert(qrcodegen_VERSION_MIN <= version && version <= qrcodegen_VERSION_MAX); + int i = (version + 7) / 17; + switch (mode) { + case qrcodegen_Mode_NUMERIC: { + static const int temp[] = {10, 12, 14}; + return temp[i]; + } + case qrcodegen_Mode_ALPHANUMERIC: { + static const int temp[] = {9, 11, 13}; + return temp[i]; + } + case qrcodegen_Mode_BYTE: { + static const int temp[] = {8, 16, 16}; + return temp[i]; + } + case qrcodegen_Mode_KANJI: { + static const int temp[] = {8, 10, 12}; + return temp[i]; + } + case qrcodegen_Mode_ECI: + return 0; + default: + assert(false); + return -1; // Dummy value + } } diff --git a/src/checks.c b/src/checks.c index 2a21c48b8..ae253f2fb 100644 --- a/src/checks.c +++ b/src/checks.c @@ -1,20 +1,20 @@ /******************************************************************************* -* Ledger Nano S - Secure firmware -* (c) 2022 Ledger -* -* Licensed under the Apache License, Version 2.0 (the "License"); -* you may not use this file except in compliance with the License. -* You may obtain a copy of the License at -* -* http://www.apache.org/licenses/LICENSE-2.0 -* -* Unless required by applicable law or agreed to in writing, software -* distributed under the License is distributed on an "AS IS" BASIS, -* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -* See the License for the specific language governing permissions and -* limitations under the License. -********************************************************************************/ + * Ledger Nano S - Secure firmware + * (c) 2022 Ledger + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT 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(HAVE_BOLOS) && defined(HAVE_PENDING_REVIEW_SCREEN) @@ -33,29 +33,36 @@ extern unsigned int const _install_parameters; static int audited_ux_slot; -static bool ui_audited_done(void) { - return !G_ux.stack[audited_ux_slot].button_push_callback; +static bool ui_audited_done(void) +{ + return !G_ux.stack[audited_ux_slot].button_push_callback; } // This function is the button callback associated with the 'ui_audited_elements' array below. -static unsigned int ui_audited_elements_button(unsigned int button_mask, unsigned int button_mask_counter __attribute__((unused))) { - unsigned int slot; - - // As soon as the user presses both buttons, we reinitialize the UX and buttons, - // and the hand is given back to the normal process. - if ((button_mask & (BUTTON_EVT_RELEASED | BUTTON_LEFT | BUTTON_RIGHT)) == (BUTTON_EVT_RELEASED | BUTTON_LEFT | BUTTON_RIGHT)) { - // We find the correct slot. - for (slot = 0x00; slot < G_ux.stack_count; slot++) { - if (G_ux.stack[slot].button_push_callback == ui_audited_elements_button) { - G_ux.stack[slot].button_push_callback = NULL; - break; - } +static unsigned int ui_audited_elements_button(unsigned int button_mask, + unsigned int button_mask_counter + __attribute__((unused))) +{ + unsigned int slot; + + // As soon as the user presses both buttons, we reinitialize the UX and buttons, + // and the hand is given back to the normal process. + if ((button_mask & (BUTTON_EVT_RELEASED | BUTTON_LEFT | BUTTON_RIGHT)) + == (BUTTON_EVT_RELEASED | BUTTON_LEFT | BUTTON_RIGHT)) { + // We find the correct slot. + for (slot = 0x00; slot < G_ux.stack_count; slot++) { + if (G_ux.stack[slot].button_push_callback == ui_audited_elements_button) { + G_ux.stack[slot].button_push_callback = NULL; + break; + } + } } - } - return 0; + return 0; } -// This array is to be displayed under specific circumstances, right at the launch of an application. +// This array is to be displayed under specific circumstances, right at the launch of an +// application. +// clang-format off const bagl_element_t ui_audited_elements[] = { #if (BAGL_WIDTH==128 && BAGL_HEIGHT==32) // Erasure of the whole screen, @@ -93,99 +100,108 @@ const bagl_element_t ui_audited_elements[] = { #error "BAGL_WIDTH/BAGL_HEIGHT not defined" #endif // (BAGL_WIDTH==128 && BAGL_HEIGHT==64) }; - -void ui_audited_init(void) { - // We reserve the first slot for this display. - audited_ux_slot = ux_stack_push(); - ux_stack_init(audited_ux_slot); - - // We trigger the additional display and wait for it to be completed. - G_ux.stack[audited_ux_slot].element_arrays[0].element_array = ui_audited_elements; - G_ux.stack[audited_ux_slot].element_arrays[0].element_array_count = sizeof(ui_audited_elements) / sizeof(ui_audited_elements[0]); - G_ux.stack[audited_ux_slot].button_push_callback = ui_audited_elements_button; - G_ux.stack[audited_ux_slot].screen_before_element_display_callback = NULL; - UX_WAKE_UP(); - UX_DISPLAY_NEXT_ELEMENT(); - UX_WAIT_DISPLAYED(); +// clang-format on + +void ui_audited_init(void) +{ + // We reserve the first slot for this display. + audited_ux_slot = ux_stack_push(); + ux_stack_init(audited_ux_slot); + + // We trigger the additional display and wait for it to be completed. + G_ux.stack[audited_ux_slot].element_arrays[0].element_array = ui_audited_elements; + G_ux.stack[audited_ux_slot].element_arrays[0].element_array_count + = sizeof(ui_audited_elements) / sizeof(ui_audited_elements[0]); + G_ux.stack[audited_ux_slot].button_push_callback = ui_audited_elements_button; + G_ux.stack[audited_ux_slot].screen_before_element_display_callback = NULL; + UX_WAKE_UP(); + UX_DISPLAY_NEXT_ELEMENT(); + UX_WAIT_DISPLAYED(); } -void ui_audited_deinit(void) { - // We pop the reserved slot but we do not care about the returned value (since we do not need it for - // further displays at the moment) and reinitialize the UX and buttons. - ux_stack_pop(); - io_seproxyhal_init_ux(); - io_seproxyhal_init_button(); +void ui_audited_deinit(void) +{ + // We pop the reserved slot but we do not care about the returned value (since we do not need it + // for + // further displays at the moment) and reinitialize the UX and buttons. + ux_stack_pop(); + io_seproxyhal_init_ux(); + io_seproxyhal_init_button(); } -#endif // HAVE_BAGL +#endif // HAVE_BAGL #ifdef HAVE_NBGL #include "nbgl_use_case.h" static bool auditChoiceMade; -static bool ui_audited_done(void) { - return auditChoiceMade; +static bool ui_audited_done(void) +{ + return auditChoiceMade; } -void ui_audited_choice(bool choice) { - if (choice) { - auditChoiceMade = choice; - } else { - os_sched_exit(0); - } +void ui_audited_choice(bool choice) +{ + if (choice) { + auditChoiceMade = choice; + } + else { + os_sched_exit(0); + } } -void ui_audited_init(void) { - auditChoiceMade = false; - nbgl_useCaseChoice(&C_warning64px, - "Pending Ledger review", - "This app has not been\nreviewed by Ledger", - "Open", - "Don't open", - ui_audited_choice); +void ui_audited_init(void) +{ + auditChoiceMade = false; + nbgl_useCaseChoice(&C_warning64px, + "Pending Ledger review", + "This app has not been\nreviewed by Ledger", + "Open", + "Don't open", + ui_audited_choice); } void ui_audited_deinit(void) {} -#endif // HAVE_NBGL +#endif // HAVE_NBGL // This function is called at the end of the seph initialization. // It checks the install parameters of the application to be run, and if this area contains the // CHECK_NOT_AUDITED_TLV_TAG tag with the CHECK_NOT_AUDITED_TLV_VAL value, a specific display // is triggered before the actual application's splash screen. -void check_audited_app(void) { - unsigned char data = BOLOS_FALSE; - unsigned char* buffer = &data; - unsigned int length = os_parse_bertlv((unsigned char*)(&_install_parameters), - CHECK_NOT_AUDITED_MAX_LEN, - NULL, - CHECK_NOT_AUDITED_TLV_TAG, - 0x00, - (void**)&buffer, - sizeof(data)); - - // We trigger the associated behaviour only when the tag was present and the value corresponds to - // the expected one. - if ( (length) - && (CHECK_NOT_AUDITED_TLV_VAL == data)) - { - ui_audited_init(); - io_seproxyhal_general_status(); - - // We wait for the button callback pointer to be wiped, and we process the incoming MCU events in the - // meantime. This callback will be wiped within the actual 'ui_audited_elements_button' function, - // as soon as the user presses both buttons. - do { - io_seproxyhal_spi_recv(G_io_seproxyhal_spi_buffer, sizeof(G_io_seproxyhal_spi_buffer), 0); - io_seproxyhal_handle_event(); - io_seproxyhal_general_status(); - } while (!ui_audited_done()); - - ui_audited_deinit(); - - // Now we can wait for the next MCU status and exit. - io_seproxyhal_spi_recv(G_io_seproxyhal_spi_buffer, sizeof(G_io_seproxyhal_spi_buffer), 0); - } +void check_audited_app(void) +{ + unsigned char data = BOLOS_FALSE; + unsigned char *buffer = &data; + unsigned int length = os_parse_bertlv((unsigned char *) (&_install_parameters), + CHECK_NOT_AUDITED_MAX_LEN, + NULL, + CHECK_NOT_AUDITED_TLV_TAG, + 0x00, + (void **) &buffer, + sizeof(data)); + + // We trigger the associated behaviour only when the tag was present and the value corresponds + // to the expected one. + if ((length) && (CHECK_NOT_AUDITED_TLV_VAL == data)) { + ui_audited_init(); + io_seproxyhal_general_status(); + + // We wait for the button callback pointer to be wiped, and we process the incoming MCU + // events in the meantime. This callback will be wiped within the actual + // 'ui_audited_elements_button' function, as soon as the user presses both buttons. + do { + io_seproxyhal_spi_recv( + G_io_seproxyhal_spi_buffer, sizeof(G_io_seproxyhal_spi_buffer), 0); + io_seproxyhal_handle_event(); + io_seproxyhal_general_status(); + } while (!ui_audited_done()); + + ui_audited_deinit(); + + // Now we can wait for the next MCU status and exit. + io_seproxyhal_spi_recv(G_io_seproxyhal_spi_buffer, sizeof(G_io_seproxyhal_spi_buffer), 0); + } } -#endif // !defined(HAVE_BOLOS) && defined(HAVE_PENDING_REVIEW_SCREEN) +#endif // !defined(HAVE_BOLOS) && defined(HAVE_PENDING_REVIEW_SCREEN) diff --git a/src/ledger_protocol.c b/src/ledger_protocol.c index f4afd2ea3..5f2a23c5e 100644 --- a/src/ledger_protocol.c +++ b/src/ledger_protocol.c @@ -1,20 +1,20 @@ /******************************************************************************* -* Ledger Nano S - Secure firmware -* (c) 2022 Ledger -* -* Licensed under the Apache License, Version 2.0 (the "License"); -* you may not use this file except in compliance with the License. -* You may obtain a copy of the License at -* -* http://www.apache.org/licenses/LICENSE-2.0 -* -* Unless required by applicable law or agreed to in writing, software -* distributed under the License is distributed on an "AS IS" BASIS, -* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -* See the License for the specific language governing permissions and -* limitations under the License. -********************************************************************************/ + * Ledger Nano S - Secure firmware + * (c) 2022 Ledger + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT 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 @@ -40,14 +40,14 @@ #ifdef HAVE_PRINTF #define LOG_BLE_PROTOCOL PRINTF -#else // !HAVE_PRINTF +#else // !HAVE_PRINTF #define LOG_BLE_PROTOCOL(...) -#endif // !HAVE_PRINTF +#endif // !HAVE_PRINTF /* Private macros-------------------------------------------------------------*/ /* Private functions prototypes ----------------------------------------------*/ -static void process_apdu_chunk(uint8_t* buffer, uint16_t length); +static void process_apdu_chunk(uint8_t *buffer, uint16_t length); /* Exported variables --------------------------------------------------------*/ @@ -57,183 +57,169 @@ static const uint8_t protocol_version[4] = {0x00, 0x00, 0x00, 0x00}; static ledger_protocol_t *ledger_protocol; /* Private functions ---------------------------------------------------------*/ -static void process_apdu_chunk(uint8_t* buffer, uint16_t length) +static void process_apdu_chunk(uint8_t *buffer, uint16_t length) { - // Check the sequence number - if ( (length < 2) - || ((uint16_t)U2BE(buffer, 0) != ledger_protocol->rx_apdu_sequence_number) - ) { - ledger_protocol->rx_apdu_status = APDU_STATUS_WAITING; - return; - } - // Check total length presence - if ( (length < 4) - && (ledger_protocol->rx_apdu_sequence_number == 0) - ) { - ledger_protocol->rx_apdu_status = APDU_STATUS_WAITING; - return; - } - - if (ledger_protocol->rx_apdu_sequence_number == 0) { - // First chunk - ledger_protocol->rx_apdu_status = APDU_STATUS_NEED_MORE_DATA; - ledger_protocol->rx_apdu_length = (uint16_t)U2BE(buffer, 2); - // Check if we have enough space to store the apdu - if (ledger_protocol->rx_apdu_length > ledger_protocol->rx_apdu_buffer_max_length) { - LOG_BLE_PROTOCOL("APDU WAITING - %d\n", ledger_protocol->rx_apdu_length); - ledger_protocol->rx_apdu_length = 0; - ledger_protocol->rx_apdu_status = APDU_STATUS_WAITING; - return; - } - ledger_protocol->rx_apdu_offset = 0; - buffer = &buffer[4]; - length -= 4; - } - else { - // Next chunk - buffer = &buffer[2]; - length -= 2; - } - - if ((ledger_protocol->rx_apdu_offset+length) > ledger_protocol->rx_apdu_length) { - length = ledger_protocol->rx_apdu_length-ledger_protocol->rx_apdu_offset; - } - - memcpy(&ledger_protocol->rx_apdu_buffer[ledger_protocol->rx_apdu_offset], - buffer, length); - ledger_protocol->rx_apdu_offset += length; - - if (ledger_protocol->rx_apdu_offset == ledger_protocol->rx_apdu_length) { - ledger_protocol->rx_apdu_sequence_number = 0; - ledger_protocol->rx_apdu_status = APDU_STATUS_COMPLETE; - LOG_BLE_PROTOCOL("APDU COMPLETE\n"); - } - else { - ledger_protocol->rx_apdu_sequence_number++; - ledger_protocol->rx_apdu_status = APDU_STATUS_NEED_MORE_DATA; - LOG_BLE_PROTOCOL("APDU NEED MORE DATA\n"); - } + // Check the sequence number + if ((length < 2) || ((uint16_t) U2BE(buffer, 0) != ledger_protocol->rx_apdu_sequence_number)) { + ledger_protocol->rx_apdu_status = APDU_STATUS_WAITING; + return; + } + // Check total length presence + if ((length < 4) && (ledger_protocol->rx_apdu_sequence_number == 0)) { + ledger_protocol->rx_apdu_status = APDU_STATUS_WAITING; + return; + } + + if (ledger_protocol->rx_apdu_sequence_number == 0) { + // First chunk + ledger_protocol->rx_apdu_status = APDU_STATUS_NEED_MORE_DATA; + ledger_protocol->rx_apdu_length = (uint16_t) U2BE(buffer, 2); + // Check if we have enough space to store the apdu + if (ledger_protocol->rx_apdu_length > ledger_protocol->rx_apdu_buffer_max_length) { + LOG_BLE_PROTOCOL("APDU WAITING - %d\n", ledger_protocol->rx_apdu_length); + ledger_protocol->rx_apdu_length = 0; + ledger_protocol->rx_apdu_status = APDU_STATUS_WAITING; + return; + } + ledger_protocol->rx_apdu_offset = 0; + buffer = &buffer[4]; + length -= 4; + } + else { + // Next chunk + buffer = &buffer[2]; + length -= 2; + } + + if ((ledger_protocol->rx_apdu_offset + length) > ledger_protocol->rx_apdu_length) { + length = ledger_protocol->rx_apdu_length - ledger_protocol->rx_apdu_offset; + } + + memcpy(&ledger_protocol->rx_apdu_buffer[ledger_protocol->rx_apdu_offset], buffer, length); + ledger_protocol->rx_apdu_offset += length; + + if (ledger_protocol->rx_apdu_offset == ledger_protocol->rx_apdu_length) { + ledger_protocol->rx_apdu_sequence_number = 0; + ledger_protocol->rx_apdu_status = APDU_STATUS_COMPLETE; + LOG_BLE_PROTOCOL("APDU COMPLETE\n"); + } + else { + ledger_protocol->rx_apdu_sequence_number++; + ledger_protocol->rx_apdu_status = APDU_STATUS_NEED_MORE_DATA; + LOG_BLE_PROTOCOL("APDU NEED MORE DATA\n"); + } } /* Exported functions --------------------------------------------------------*/ void LEDGER_PROTOCOL_init(ledger_protocol_t *data) { - ledger_protocol = data; - ledger_protocol->rx_apdu_status = APDU_STATUS_WAITING; - ledger_protocol->rx_apdu_sequence_number = 0; + ledger_protocol = data; + ledger_protocol->rx_apdu_status = APDU_STATUS_WAITING; + ledger_protocol->rx_apdu_sequence_number = 0; } -void LEDGER_PROTOCOL_rx(uint8_t *buffer, - uint16_t length) +void LEDGER_PROTOCOL_rx(uint8_t *buffer, uint16_t length) { - if (!buffer || length < 3) { - return; - } - - memset(ledger_protocol->tx_chunk, 0, sizeof(ledger_protocol->tx_chunk)); - memcpy(ledger_protocol->tx_chunk, buffer, 2); // Copy channel ID - - switch (buffer[2]) { - - case TAG_GET_PROTOCOL_VERSION: - LOG_BLE_PROTOCOL("TAG_GET_PROTOCOL_VERSION\n"); - ledger_protocol->tx_chunk[2] = TAG_GET_PROTOCOL_VERSION; - ledger_protocol->tx_chunk_length = MIN(sizeof(protocol_version), - (sizeof(ledger_protocol->tx_chunk)-3)); - memcpy(&ledger_protocol->tx_chunk[3], - protocol_version, - ledger_protocol->tx_chunk_length); - ledger_protocol->tx_chunk_length += 3; - break; - - case TAG_ALLOCATE_CHANNEL: - LOG_BLE_PROTOCOL("TAG_ALLOCATE_CHANNEL\n"); - ledger_protocol->tx_chunk[2] = TAG_ALLOCATE_CHANNEL; - ledger_protocol->tx_chunk_length = 3; - break; - - case TAG_PING: - LOG_BLE_PROTOCOL("TAG_PING\n"); - ledger_protocol->tx_chunk_length = MIN(sizeof(ledger_protocol->tx_chunk), - length); - memcpy(ledger_protocol->tx_chunk, - buffer, - ledger_protocol->tx_chunk_length); - break; - - case TAG_APDU: - LOG_BLE_PROTOCOL("TAG_APDU\n"); - process_apdu_chunk(&buffer[3], length-3); - break; - - case TAG_MTU: - LOG_BLE_PROTOCOL("TAG_MTU\n"); - ledger_protocol->tx_chunk[2] = TAG_MTU; - ledger_protocol->tx_chunk[3] = 0x00; - ledger_protocol->tx_chunk[4] = 0x00; - ledger_protocol->tx_chunk[5] = 0x00; - ledger_protocol->tx_chunk[6] = 0x01; - ledger_protocol->tx_chunk[7] = ledger_protocol->mtu-2; - ledger_protocol->tx_chunk_length = 8; - break; - - default: - // Unsupported command - break; - } + if (!buffer || length < 3) { + return; + } + + memset(ledger_protocol->tx_chunk, 0, sizeof(ledger_protocol->tx_chunk)); + memcpy(ledger_protocol->tx_chunk, buffer, 2); // Copy channel ID + + switch (buffer[2]) { + case TAG_GET_PROTOCOL_VERSION: + LOG_BLE_PROTOCOL("TAG_GET_PROTOCOL_VERSION\n"); + ledger_protocol->tx_chunk[2] = TAG_GET_PROTOCOL_VERSION; + ledger_protocol->tx_chunk_length + = MIN(sizeof(protocol_version), (sizeof(ledger_protocol->tx_chunk) - 3)); + memcpy( + &ledger_protocol->tx_chunk[3], protocol_version, ledger_protocol->tx_chunk_length); + ledger_protocol->tx_chunk_length += 3; + break; + + case TAG_ALLOCATE_CHANNEL: + LOG_BLE_PROTOCOL("TAG_ALLOCATE_CHANNEL\n"); + ledger_protocol->tx_chunk[2] = TAG_ALLOCATE_CHANNEL; + ledger_protocol->tx_chunk_length = 3; + break; + + case TAG_PING: + LOG_BLE_PROTOCOL("TAG_PING\n"); + ledger_protocol->tx_chunk_length = MIN(sizeof(ledger_protocol->tx_chunk), length); + memcpy(ledger_protocol->tx_chunk, buffer, ledger_protocol->tx_chunk_length); + break; + + case TAG_APDU: + LOG_BLE_PROTOCOL("TAG_APDU\n"); + process_apdu_chunk(&buffer[3], length - 3); + break; + + case TAG_MTU: + LOG_BLE_PROTOCOL("TAG_MTU\n"); + ledger_protocol->tx_chunk[2] = TAG_MTU; + ledger_protocol->tx_chunk[3] = 0x00; + ledger_protocol->tx_chunk[4] = 0x00; + ledger_protocol->tx_chunk[5] = 0x00; + ledger_protocol->tx_chunk[6] = 0x01; + ledger_protocol->tx_chunk[7] = ledger_protocol->mtu - 2; + ledger_protocol->tx_chunk_length = 8; + break; + + default: + // Unsupported command + break; + } } -void LEDGER_PROTOCOL_tx(uint8_t *buffer, - uint16_t length) +void LEDGER_PROTOCOL_tx(uint8_t *buffer, uint16_t length) { - if (!buffer && !ledger_protocol->tx_apdu_buffer) { - return; - } - if (buffer) { - LOG_BLE_PROTOCOL("FIRST CHUNK"); - ledger_protocol->tx_apdu_buffer = buffer; - ledger_protocol->tx_apdu_length = length; - ledger_protocol->tx_apdu_sequence_number = 0; - ledger_protocol->tx_apdu_offset = 0; - memset(ledger_protocol->tx_chunk, 0, sizeof(ledger_protocol->tx_chunk)); - } - else { - LOG_BLE_PROTOCOL("NEXT CHUNK"); - } - - uint16_t tx_chunk_offset = 2; // Because channel id has been already filled beforehand - - ledger_protocol->tx_chunk[tx_chunk_offset++] = TAG_APDU; - - U2BE_ENCODE(ledger_protocol->tx_chunk, - tx_chunk_offset, - ledger_protocol->tx_apdu_sequence_number); - tx_chunk_offset += 2; - - if (ledger_protocol->tx_apdu_sequence_number == 0) { - U2BE_ENCODE(ledger_protocol->tx_chunk, - tx_chunk_offset, - ledger_protocol->tx_apdu_length); - tx_chunk_offset += 2; - } - if ((ledger_protocol->tx_apdu_length+tx_chunk_offset) >= (ledger_protocol->mtu+ledger_protocol->tx_apdu_offset)) { - // Remaining buffer length doesn't fit the chunk - memcpy(&ledger_protocol->tx_chunk[tx_chunk_offset], - &ledger_protocol->tx_apdu_buffer[ledger_protocol->tx_apdu_offset], - ledger_protocol->mtu-tx_chunk_offset); - ledger_protocol->tx_apdu_offset += ledger_protocol->mtu-tx_chunk_offset; - ledger_protocol->tx_apdu_sequence_number++; - tx_chunk_offset = ledger_protocol->mtu; - } - else { - // Remaining buffer fits the chunk TODO pad for usb - memcpy(&ledger_protocol->tx_chunk[tx_chunk_offset], - &ledger_protocol->tx_apdu_buffer[ledger_protocol->tx_apdu_offset], - ledger_protocol->tx_apdu_length-ledger_protocol->tx_apdu_offset); - tx_chunk_offset += (ledger_protocol->tx_apdu_length-ledger_protocol->tx_apdu_offset); - ledger_protocol->tx_apdu_offset = ledger_protocol->tx_apdu_length; - ledger_protocol->tx_apdu_buffer = NULL; - } - ledger_protocol->tx_chunk_length = tx_chunk_offset; - LOG_BLE_PROTOCOL(" %d\n", ledger_protocol->tx_chunk_length); + if (!buffer && !ledger_protocol->tx_apdu_buffer) { + return; + } + if (buffer) { + LOG_BLE_PROTOCOL("FIRST CHUNK"); + ledger_protocol->tx_apdu_buffer = buffer; + ledger_protocol->tx_apdu_length = length; + ledger_protocol->tx_apdu_sequence_number = 0; + ledger_protocol->tx_apdu_offset = 0; + memset(ledger_protocol->tx_chunk, 0, sizeof(ledger_protocol->tx_chunk)); + } + else { + LOG_BLE_PROTOCOL("NEXT CHUNK"); + } + + uint16_t tx_chunk_offset = 2; // Because channel id has been already filled beforehand + + ledger_protocol->tx_chunk[tx_chunk_offset++] = TAG_APDU; + + U2BE_ENCODE( + ledger_protocol->tx_chunk, tx_chunk_offset, ledger_protocol->tx_apdu_sequence_number); + tx_chunk_offset += 2; + + if (ledger_protocol->tx_apdu_sequence_number == 0) { + U2BE_ENCODE(ledger_protocol->tx_chunk, tx_chunk_offset, ledger_protocol->tx_apdu_length); + tx_chunk_offset += 2; + } + if ((ledger_protocol->tx_apdu_length + tx_chunk_offset) + >= (ledger_protocol->mtu + ledger_protocol->tx_apdu_offset)) { + // Remaining buffer length doesn't fit the chunk + memcpy(&ledger_protocol->tx_chunk[tx_chunk_offset], + &ledger_protocol->tx_apdu_buffer[ledger_protocol->tx_apdu_offset], + ledger_protocol->mtu - tx_chunk_offset); + ledger_protocol->tx_apdu_offset += ledger_protocol->mtu - tx_chunk_offset; + ledger_protocol->tx_apdu_sequence_number++; + tx_chunk_offset = ledger_protocol->mtu; + } + else { + // Remaining buffer fits the chunk TODO pad for usb + memcpy(&ledger_protocol->tx_chunk[tx_chunk_offset], + &ledger_protocol->tx_apdu_buffer[ledger_protocol->tx_apdu_offset], + ledger_protocol->tx_apdu_length - ledger_protocol->tx_apdu_offset); + tx_chunk_offset += (ledger_protocol->tx_apdu_length - ledger_protocol->tx_apdu_offset); + ledger_protocol->tx_apdu_offset = ledger_protocol->tx_apdu_length; + ledger_protocol->tx_apdu_buffer = NULL; + } + ledger_protocol->tx_chunk_length = tx_chunk_offset; + LOG_BLE_PROTOCOL(" %d\n", ledger_protocol->tx_chunk_length); } diff --git a/src/os.c b/src/os.c index e442b030b..232b82375 100644 --- a/src/os.c +++ b/src/os.c @@ -1,20 +1,20 @@ /******************************************************************************* -* Ledger Nano S - Secure firmware -* (c) 2022 Ledger -* -* Licensed under the Apache License, Version 2.0 (the "License"); -* you may not use this file except in compliance with the License. -* You may obtain a copy of the License at -* -* http://www.apache.org/licenses/LICENSE-2.0 -* -* Unless required by applicable law or agreed to in writing, software -* distributed under the License is distributed on an "AS IS" BASIS, -* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -* See the License for the specific language governing permissions and -* limitations under the License. -********************************************************************************/ + * Ledger Nano S - Secure firmware + * (c) 2022 Ledger + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT 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 "exceptions.h" #include "lcx_rng.h" @@ -30,54 +30,58 @@ unsigned char G_io_apdu_buffer[IO_APDU_BUFFER_SIZE]; #endif #ifndef BOLOS_OS_UPGRADER_APP -void os_boot(void) { - // // TODO patch entry point when romming (f) - // // set the default try context to nothing +void os_boot(void) +{ + // // TODO patch entry point when romming (f) + // // set the default try context to nothing #ifndef HAVE_BOLOS - try_context_set(NULL); -#endif // HAVE_BOLOS + try_context_set(NULL); +#endif // HAVE_BOLOS } -#endif // BOLOS_OS_UPGRADER_APP +#endif // BOLOS_OS_UPGRADER_APP -void os_memset4(void* dst, unsigned int initval, unsigned int nbintval) { - while(nbintval--) { - ((unsigned int*) dst)[nbintval] = initval; - } +void os_memset4(void *dst, unsigned int initval, unsigned int nbintval) +{ + while (nbintval--) { + ((unsigned int *) dst)[nbintval] = initval; + } } -void os_xor(void * dst, void * src1, void * src2, unsigned int length) { -#define SRC1 ((unsigned char const *)src1) -#define SRC2 ((unsigned char const *)src2) -#define DST ((unsigned char *)dst) - unsigned int l = length; - // don't || to ensure all condition are evaluated - while(!(!length && !l)) { - length--; - DST[length] = SRC1[length] ^ SRC2[length]; - l--; - } - // WHAT ??? glitch detected ? - if (*((volatile unsigned int*)&l)!= *((volatile unsigned int*)&length)) { - THROW(EXCEPTION); - } +void os_xor(void *dst, void *src1, void *src2, unsigned int length) +{ +#define SRC1 ((unsigned char const *) src1) +#define SRC2 ((unsigned char const *) src2) +#define DST ((unsigned char *) dst) + unsigned int l = length; + // don't || to ensure all condition are evaluated + while (!(!length && !l)) { + length--; + DST[length] = SRC1[length] ^ SRC2[length]; + l--; + } + // WHAT ??? glitch detected ? + if (*((volatile unsigned int *) &l) != *((volatile unsigned int *) &length)) { + THROW(EXCEPTION); + } } -char os_secure_memcmp(const void *src1, const void* src2, size_t length) { -#define SRC1 ((unsigned char const *)src1) -#define SRC2 ((unsigned char const *)src2) - unsigned int l = length; - unsigned char xoracc=0; - // don't || to ensure all condition are evaluated - while(!(!length && !l)) { - length--; - xoracc |= SRC1[length] ^ SRC2[length]; - l--; - } - // WHAT ??? glitch detected ? - if (*(volatile unsigned int*)&l!=*(volatile unsigned int*)&length) { - THROW(EXCEPTION); - } - return xoracc; +char os_secure_memcmp(const void *src1, const void *src2, size_t length) +{ +#define SRC1 ((unsigned char const *) src1) +#define SRC2 ((unsigned char const *) src2) + unsigned int l = length; + unsigned char xoracc = 0; + // don't || to ensure all condition are evaluated + while (!(!length && !l)) { + length--; + xoracc |= SRC1[length] ^ SRC2[length]; + l--; + } + // WHAT ??? glitch detected ? + if (*(volatile unsigned int *) &l != *(volatile unsigned int *) &length) { + THROW(EXCEPTION); + } + return xoracc; } #ifndef HAVE_BOLOS @@ -85,219 +89,236 @@ char os_secure_memcmp(const void *src1, const void* src2, size_t length) { int main(void); // This function can be used to declare a callback to THROW in the application -__attribute((weak)) void app_throw_info(unsigned int exception, unsigned int lr_val) { - UNUSED(exception); - UNUSED(lr_val); +__attribute((weak)) void app_throw_info(unsigned int exception, unsigned int lr_val) +{ + UNUSED(exception); + UNUSED(lr_val); } -void os_longjmp(unsigned int exception) { - unsigned int lr_val; - __asm volatile("mov %0, lr" :"=r"(lr_val)); +void os_longjmp(unsigned int exception) +{ + unsigned int lr_val; + __asm volatile("mov %0, lr" : "=r"(lr_val)); - // Compute location before relocation (sort of anti PIC) - lr_val = lr_val - (unsigned int)main + MAIN_LINKER_SCRIPT_LOCATION; + // Compute location before relocation (sort of anti PIC) + lr_val = lr_val - (unsigned int) main + MAIN_LINKER_SCRIPT_LOCATION; #ifdef HAVE_PRINTF - PRINTF("exception[%d]: LR=0x%08X\n", exception, lr_val); -#endif // HAVE_PRINTF + PRINTF("exception[%d]: LR=0x%08X\n", exception, lr_val); +#endif // HAVE_PRINTF - // Send to the app the info of exception and LR for debug purpose - app_throw_info(exception, lr_val); + // Send to the app the info of exception and LR for debug purpose + app_throw_info(exception, lr_val); - longjmp(try_context_get()->jmp_buf, exception); + longjmp(try_context_get()->jmp_buf, exception); } -#endif // HAVE_BOLOS +#endif // HAVE_BOLOS // BER encoded // // tag: 1 byte only -// length: 1 byte if little than 0x80, else 1 byte of length encoding (0x8Y, with Y the number of following bytes the length is encoded on) and then Y bytes of BE encoded total length -// value: no encoding, raw data -unsigned int os_parse_bertlv(unsigned char* mem, unsigned int mem_len, - unsigned int * tlvoffset, unsigned int tag, unsigned int offset, void** buffer, unsigned int maxlength) { - unsigned int ret, tlvoffset_in; - unsigned int check_equals_buffer = offset & OS_PARSE_BERTLV_OFFSET_COMPARE_WITH_BUFFER; - unsigned int get_address = offset & OS_PARSE_BERTLV_OFFSET_GET_LENGTH; - offset &= ~(OS_PARSE_BERTLV_OFFSET_COMPARE_WITH_BUFFER|OS_PARSE_BERTLV_OFFSET_GET_LENGTH); - - // nothing to be read - if (mem_len == 0 || buffer == NULL || (!get_address && *buffer == NULL)) { - return 0; - } - - // the tlv start address - unsigned char* tlv = (unsigned char*) mem; - unsigned int remlen = mem_len; - ret = 0; - - // account for a shift in the tlv list before parsing - tlvoffset_in = 0; - if (tlvoffset) { - tlvoffset_in = *tlvoffset; - } - - // parse tlv until some tag to parse - while(remlen>=2) { - // tag matches - unsigned int tlvtag = *tlv++; - remlen--; - unsigned int tlvlen = *tlv++; - remlen--; - if (remlen == 0) { - goto retret; +// length: 1 byte if little than 0x80, else 1 byte of length encoding (0x8Y, with Y the number of +// following bytes the length is encoded on) and then Y bytes of BE encoded total length value: no +// encoding, raw data +unsigned int os_parse_bertlv(unsigned char *mem, + unsigned int mem_len, + unsigned int *tlvoffset, + unsigned int tag, + unsigned int offset, + void **buffer, + unsigned int maxlength) +{ + unsigned int ret, tlvoffset_in; + unsigned int check_equals_buffer = offset & OS_PARSE_BERTLV_OFFSET_COMPARE_WITH_BUFFER; + unsigned int get_address = offset & OS_PARSE_BERTLV_OFFSET_GET_LENGTH; + offset &= ~(OS_PARSE_BERTLV_OFFSET_COMPARE_WITH_BUFFER | OS_PARSE_BERTLV_OFFSET_GET_LENGTH); + + // nothing to be read + if (mem_len == 0 || buffer == NULL || (!get_address && *buffer == NULL)) { + return 0; } - if (tlvlen >= 0x80) { - // invalid encoding - if (tlvlen == 0x80) { - goto retret; - } - unsigned int tlvlenlen_ = tlvlen & 0x7F; - tlvlen = 0; - while(tlvlenlen_--) { - // BE encoded - tlvlen = (tlvlen << 8) | ((*tlv++)&0xFF); + + // the tlv start address + unsigned char *tlv = (unsigned char *) mem; + unsigned int remlen = mem_len; + ret = 0; + + // account for a shift in the tlv list before parsing + tlvoffset_in = 0; + if (tlvoffset) { + tlvoffset_in = *tlvoffset; + } + + // parse tlv until some tag to parse + while (remlen >= 2) { + // tag matches + unsigned int tlvtag = *tlv++; + remlen--; + unsigned int tlvlen = *tlv++; remlen--; if (remlen == 0) { - goto retret; + goto retret; } - } - } - // check if tag matches - if (tlvtag == (tag&0xFF)) { - if (tlvoffset) { - unsigned int o = (unsigned int) tlv - (unsigned int)mem; - // compute the current position in the tlv bytes - *tlvoffset = o; - - // skip the tag if the requested tlvoffset has not been matched yet. - if (tlvoffset_in>o) { - goto next_tlv; + if (tlvlen >= 0x80) { + // invalid encoding + if (tlvlen == 0x80) { + goto retret; + } + unsigned int tlvlenlen_ = tlvlen & 0x7F; + tlvlen = 0; + while (tlvlenlen_--) { + // BE encoded + tlvlen = (tlvlen << 8) | ((*tlv++) & 0xFF); + remlen--; + if (remlen == 0) { + goto retret; + } + } } - } - // avoid OOB - if (offset > tlvlen || offset > remlen) { - goto retret; - } - - // check maxlength is respected for equality - if (check_equals_buffer && (tlvlen-offset) != maxlength) { - // buffer to check the complete given length - goto retret; - } - - maxlength = MIN(maxlength, MIN(tlvlen-offset, remlen)); - // robustness check to avoid memory dumping, only allowing data space dumps - if ( - offset > mem_len - || maxlength > mem_len - || offset+maxlength > mem_len - // don't rely only on provided app bounds to avoid address forgery - || (unsigned int)tlv < (unsigned int)mem - || (unsigned int)tlv+offset < (unsigned int)mem - || (unsigned int)tlv+offset+maxlength < (unsigned int)mem - || (unsigned int)tlv > (unsigned int)mem+mem_len - || (unsigned int)tlv+offset > (unsigned int)mem+mem_len - || (unsigned int)tlv+offset+maxlength > (unsigned int)mem+mem_len) { - goto retret; - } - - // retrieve the tlv's data content at the requested offset, and return the total data length - if (get_address) { - *buffer = tlv+offset; - // return the tlv's total length from requested offset - ret = MIN(tlvlen-offset, remlen); - goto retret; - } - - if (!check_equals_buffer) { - memmove(*buffer, tlv+offset, maxlength); - } - else { - ret = os_secure_memcmp(*buffer, tlv+offset, maxlength) == 0; - goto retret; - } - ret = maxlength; - goto retret; + // check if tag matches + if (tlvtag == (tag & 0xFF)) { + if (tlvoffset) { + unsigned int o = (unsigned int) tlv - (unsigned int) mem; + // compute the current position in the tlv bytes + *tlvoffset = o; + + // skip the tag if the requested tlvoffset has not been matched yet. + if (tlvoffset_in > o) { + goto next_tlv; + } + } + // avoid OOB + if (offset > tlvlen || offset > remlen) { + goto retret; + } + + // check maxlength is respected for equality + if (check_equals_buffer && (tlvlen - offset) != maxlength) { + // buffer to check the complete given length + goto retret; + } + + maxlength = MIN(maxlength, MIN(tlvlen - offset, remlen)); + // robustness check to avoid memory dumping, only allowing data space dumps + if (offset > mem_len || maxlength > mem_len + || offset + maxlength > mem_len + // don't rely only on provided app bounds to avoid address forgery + || (unsigned int) tlv < (unsigned int) mem + || (unsigned int) tlv + offset < (unsigned int) mem + || (unsigned int) tlv + offset + maxlength < (unsigned int) mem + || (unsigned int) tlv > (unsigned int) mem + mem_len + || (unsigned int) tlv + offset > (unsigned int) mem + mem_len + || (unsigned int) tlv + offset + maxlength > (unsigned int) mem + mem_len) { + goto retret; + } + + // retrieve the tlv's data content at the requested offset, and return the total data + // length + if (get_address) { + *buffer = tlv + offset; + // return the tlv's total length from requested offset + ret = MIN(tlvlen - offset, remlen); + goto retret; + } + + if (!check_equals_buffer) { + memmove(*buffer, tlv + offset, maxlength); + } + else { + ret = os_secure_memcmp(*buffer, tlv + offset, maxlength) == 0; + goto retret; + } + ret = maxlength; + goto retret; + } + next_tlv: + // skip to next tlv + tlv += tlvlen; + remlen -= MIN(remlen, tlvlen); } - next_tlv: - // skip to next tlv - tlv += tlvlen; - remlen-=MIN(remlen, tlvlen); - } retret: - return ret; + return ret; } #ifndef BOLOS_OS_UPGRADER_APP -void safe_desynch(void) { - volatile int a, b; - unsigned int i; - - i = ((cx_rng_u32()&0xFF) + 1u); - a = b = 1; - while(i--) { - a = 1 + (b << (a / 2)); - b = cx_rng_u32(); - } +void safe_desynch(void) +{ + volatile int a, b; + unsigned int i; + + i = ((cx_rng_u32() & 0xFF) + 1u); + a = b = 1; + while (i--) { + a = 1 + (b << (a / 2)); + b = cx_rng_u32(); + } } -#endif // BOLOS_OS_UPGRADER_APP +#endif // BOLOS_OS_UPGRADER_APP -void u4be_encode(unsigned char* buffer, unsigned int offset, unsigned int value) { - U4BE_ENCODE(buffer, offset, value); +void u4be_encode(unsigned char *buffer, unsigned int offset, unsigned int value) +{ + U4BE_ENCODE(buffer, offset, value); } -void u4le_encode(unsigned char* buffer, unsigned int offset, unsigned int value) { - U4LE_ENCODE(buffer, offset, value); +void u4le_encode(unsigned char *buffer, unsigned int offset, unsigned int value) +{ + U4LE_ENCODE(buffer, offset, value); } -void *os_memmove(void *dest, const void *src, size_t n) { - return memmove(dest, src, n); +void *os_memmove(void *dest, const void *src, size_t n) +{ + return memmove(dest, src, n); } -void *os_memcpy(void *dest, const void *src, size_t n) { - return memmove(dest, src, n); +void *os_memcpy(void *dest, const void *src, size_t n) +{ + return memmove(dest, src, n); } -int os_memcmp(const void *s1, const void *s2, size_t n) { - return memcmp(s1, s2, n); +int os_memcmp(const void *s1, const void *s2, size_t n) +{ + return memcmp(s1, s2, n); } -void *os_memset(void *s, int c, size_t n) { - return memset(s, c, n); +void *os_memset(void *s, int c, size_t n) +{ + return memset(s, c, n); } -int bytes_to_hex(char *out, size_t outl, const void *value, size_t len) { - const uint8_t *bytes = (const uint8_t *) value; - const char *hex = "0123456789ABCDEF"; - - if (outl < 2 * len + 1) { - *out = '\0'; - return -1; - } - - for (size_t i = 0; i < len; i++) { - *out++ = hex[(bytes[i] >> 4) & 0xf]; - *out++ = hex[bytes[i] & 0xf]; - } - *out = 0; - return 0; +int bytes_to_hex(char *out, size_t outl, const void *value, size_t len) +{ + const uint8_t *bytes = (const uint8_t *) value; + const char *hex = "0123456789ABCDEF"; + + if (outl < 2 * len + 1) { + *out = '\0'; + return -1; + } + + for (size_t i = 0; i < len; i++) { + *out++ = hex[(bytes[i] >> 4) & 0xf]; + *out++ = hex[bytes[i] & 0xf]; + } + *out = 0; + return 0; } -int bytes_to_lowercase_hex(char *out, size_t outl, const void *value, size_t len) { - const uint8_t *bytes = (const uint8_t *) value; - const char *hex = "0123456789abcdef"; - - if (outl < 2 * len + 1) { - *out = '\0'; - return -1; - } - - for (size_t i = 0; i < len; i++) { - *out++ = hex[(bytes[i] >> 4) & 0xf]; - *out++ = hex[bytes[i] & 0xf]; - } - *out = 0; - return 0; +int bytes_to_lowercase_hex(char *out, size_t outl, const void *value, size_t len) +{ + const uint8_t *bytes = (const uint8_t *) value; + const char *hex = "0123456789abcdef"; + + if (outl < 2 * len + 1) { + *out = '\0'; + return -1; + } + + for (size_t i = 0; i < len; i++) { + *out++ = hex[(bytes[i] >> 4) & 0xf]; + *out++ = hex[bytes[i] & 0xf]; + } + *out = 0; + return 0; } // BSS start and end defines addresses @@ -305,6 +326,7 @@ extern void *_bss; extern void *_ebss; // This call will reset the value of the entire BSS segment -void os_explicit_zero_BSS_segment(void) { - explicit_bzero(&_bss, ((uintptr_t)&_ebss) - ((uintptr_t)&_bss)); +void os_explicit_zero_BSS_segment(void) +{ + explicit_bzero(&_bss, ((uintptr_t) &_ebss) - ((uintptr_t) &_bss)); } diff --git a/src/os_io_seproxyhal.c b/src/os_io_seproxyhal.c index 65a48cc55..acdc3f398 100644 --- a/src/os_io_seproxyhal.c +++ b/src/os_io_seproxyhal.c @@ -1,30 +1,30 @@ /******************************************************************************* -* Ledger Nano S - Secure firmware -* (c) 2022 Ledger -* -* Licensed under the Apache License, Version 2.0 (the "License"); -* you may not use this file except in compliance with the License. -* You may obtain a copy of the License at -* -* http://www.apache.org/licenses/LICENSE-2.0 -* -* Unless required by applicable law or agreed to in writing, software -* distributed under the License is distributed on an "AS IS" BASIS, -* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -* See the License for the specific language governing permissions and -* limitations under the License. -********************************************************************************/ + * Ledger Nano S - Secure firmware + * (c) 2022 Ledger + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT 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 "bolos_target.h" #ifdef TARGET_NANOX #ifndef HAVE_SEPROXYHAL_MCU -# define HAVE_SEPROXYHAL_MCU -#endif // HAVE_SEPROXYHAL_MCU +#define HAVE_SEPROXYHAL_MCU +#endif // HAVE_SEPROXYHAL_MCU #ifndef HAVE_MCU_PROTECT #define HAVE_MCU_PROTECT -#endif // HAVE_MCU_PROTECT -#endif // TARGET_NANOX +#endif // HAVE_MCU_PROTECT +#endif // TARGET_NANOX #include "errors.h" #include "exceptions.h" @@ -32,8 +32,8 @@ #include "os_apilevel.h" #if defined(DEBUG_OS_STACK_CONSUMPTION) -# include "os_debug.h" -#endif // DEBUG_OS_STACK_CONSUMPTION +#include "os_debug.h" +#endif // DEBUG_OS_STACK_CONSUMPTION #include "os_id.h" #include "os_io.h" @@ -51,7 +51,7 @@ #ifdef HAVE_BLE #include "ledger_ble.h" -#endif // HAVE_BLE +#endif // HAVE_BLE #if defined(HAVE_BAGL) || defined(HAVE_NBGL) #include "ux.h" @@ -61,7 +61,7 @@ #ifndef IO_RAPDU_TRANSMIT_TIMEOUT_MS #define IO_RAPDU_TRANSMIT_TIMEOUT_MS 2000UL -#endif // IO_RAPDU_TRANSMIT_TIMEOUT_MS +#endif // IO_RAPDU_TRANSMIT_TIMEOUT_MS #ifdef HAVE_IO_U2F #include "u2f_processing.h" @@ -70,7 +70,7 @@ #ifndef VERSION #define VERSION "dummy" -#endif // VERSION +#endif // VERSION #ifdef DEBUG #define LOG printf @@ -92,19 +92,19 @@ extern USBD_HandleTypeDef USBD_Device; #endif #if !defined(HAVE_BOLOS_NO_DEFAULT_APDU) -# define DEFAULT_APDU_CLA 0xB0 -# define DEFAULT_APDU_INS_GET_VERSION 0x01 +#define DEFAULT_APDU_CLA 0xB0 +#define DEFAULT_APDU_INS_GET_VERSION 0x01 -# if defined(HAVE_SEED_COOKIE) -# define DEFAULT_APDU_INS_GET_SEED_COOKIE 0x02 -# endif +#if defined(HAVE_SEED_COOKIE) +#define DEFAULT_APDU_INS_GET_SEED_COOKIE 0x02 +#endif -# if defined(DEBUG_OS_STACK_CONSUMPTION) -# define DEFAULT_APDU_INS_STACK_CONSUMPTION 0x57 -# endif // DEBUG_OS_STACK_CONSUMPTION +#if defined(DEBUG_OS_STACK_CONSUMPTION) +#define DEFAULT_APDU_INS_STACK_CONSUMPTION 0x57 +#endif // DEBUG_OS_STACK_CONSUMPTION -# define DEFAULT_APDU_INS_APP_EXIT 0xA7 -#endif // !HAVE_BOLOS_NO_DEFAULT_APDU +#define DEFAULT_APDU_INS_APP_EXIT 0xA7 +#endif // !HAVE_BOLOS_NO_DEFAULT_APDU void io_seproxyhal_handle_ble_event(void); @@ -112,363 +112,377 @@ unsigned int os_io_seph_recv_and_process(unsigned int dont_process_ux_events); #ifndef HAVE_BOLOS io_seph_app_t G_io_app; -#endif // ! HAVE_BOLOS - +#endif // ! HAVE_BOLOS #if defined(HAVE_BAGL) || defined(HAVE_NBGL) ux_seph_os_and_app_t G_ux_os; #endif -static const unsigned char seph_io_general_status[]= { - SEPROXYHAL_TAG_GENERAL_STATUS, - 0, - 2, - SEPROXYHAL_TAG_GENERAL_STATUS_LAST_COMMAND>>8, - SEPROXYHAL_TAG_GENERAL_STATUS_LAST_COMMAND, +static const unsigned char seph_io_general_status[] = { + SEPROXYHAL_TAG_GENERAL_STATUS, + 0, + 2, + SEPROXYHAL_TAG_GENERAL_STATUS_LAST_COMMAND >> 8, + SEPROXYHAL_TAG_GENERAL_STATUS_LAST_COMMAND, }; -void io_seproxyhal_general_status(void) { - // send the general status - io_seproxyhal_spi_send(seph_io_general_status, sizeof(seph_io_general_status)); +void io_seproxyhal_general_status(void) +{ + // send the general status + io_seproxyhal_spi_send(seph_io_general_status, sizeof(seph_io_general_status)); } -static const unsigned char seph_io_request_status[]= { - SEPROXYHAL_TAG_REQUEST_STATUS, - 0, - 0, +static const unsigned char seph_io_request_status[] = { + SEPROXYHAL_TAG_REQUEST_STATUS, + 0, + 0, }; -void io_seproxyhal_request_mcu_status(void) { - // send the general status - io_seproxyhal_spi_send(seph_io_request_status, sizeof(seph_io_request_status)); +void io_seproxyhal_request_mcu_status(void) +{ + // send the general status + io_seproxyhal_spi_send(seph_io_request_status, sizeof(seph_io_request_status)); } #ifdef HAVE_IO_USB #ifdef HAVE_L4_USBLIB -void io_seproxyhal_handle_usb_event(void) { - switch(G_io_seproxyhal_spi_buffer[3]) { - case SEPROXYHAL_TAG_USB_EVENT_RESET: - USBD_LL_SetSpeed(&USBD_Device, USBD_SPEED_FULL); - USBD_LL_Reset(&USBD_Device); - // ongoing APDU detected, throw a reset, even if not the media. to avoid potential troubles. - if (G_io_app.apdu_media != IO_APDU_MEDIA_NONE) { - THROW(EXCEPTION_IO_RESET); - } - memset(G_io_app.usb_ep_xfer_len, 0, sizeof(G_io_app.usb_ep_xfer_len)); - memset(G_io_app.usb_ep_timeouts, 0, sizeof(G_io_app.usb_ep_timeouts)); - break; - case SEPROXYHAL_TAG_USB_EVENT_SOF: - USBD_LL_SOF(&USBD_Device); - break; - case SEPROXYHAL_TAG_USB_EVENT_SUSPENDED: - USBD_LL_Suspend(&USBD_Device); - break; - case SEPROXYHAL_TAG_USB_EVENT_RESUMED: - USBD_LL_Resume(&USBD_Device); - break; - } +void io_seproxyhal_handle_usb_event(void) +{ + switch (G_io_seproxyhal_spi_buffer[3]) { + case SEPROXYHAL_TAG_USB_EVENT_RESET: + USBD_LL_SetSpeed(&USBD_Device, USBD_SPEED_FULL); + USBD_LL_Reset(&USBD_Device); + // ongoing APDU detected, throw a reset, even if not the media. to avoid potential + // troubles. + if (G_io_app.apdu_media != IO_APDU_MEDIA_NONE) { + THROW(EXCEPTION_IO_RESET); + } + memset(G_io_app.usb_ep_xfer_len, 0, sizeof(G_io_app.usb_ep_xfer_len)); + memset(G_io_app.usb_ep_timeouts, 0, sizeof(G_io_app.usb_ep_timeouts)); + break; + case SEPROXYHAL_TAG_USB_EVENT_SOF: + USBD_LL_SOF(&USBD_Device); + break; + case SEPROXYHAL_TAG_USB_EVENT_SUSPENDED: + USBD_LL_Suspend(&USBD_Device); + break; + case SEPROXYHAL_TAG_USB_EVENT_RESUMED: + USBD_LL_Resume(&USBD_Device); + break; + } } +void io_seproxyhal_handle_usb_ep_xfer_event(void) +{ + uint8_t epnum; + + epnum = G_io_seproxyhal_spi_buffer[3] & 0x7F; + + switch (G_io_seproxyhal_spi_buffer[4]) { + /* This event is received when a new SETUP token had been received on a control endpoint */ + case SEPROXYHAL_TAG_USB_EP_XFER_SETUP: + // assume length of setup packet, and that it is on endpoint 0 + USBD_LL_SetupStage(&USBD_Device, &G_io_seproxyhal_spi_buffer[6]); + break; + + /* This event is received after the prepare data packet has been flushed to the usb host */ + case SEPROXYHAL_TAG_USB_EP_XFER_IN: + if (epnum < IO_USB_MAX_ENDPOINTS) { + // discard ep timeout as we received the sent packet confirmation + G_io_app.usb_ep_timeouts[epnum].timeout = 0; + // propagate sending ack of the data + USBD_LL_DataInStage(&USBD_Device, epnum, &G_io_seproxyhal_spi_buffer[6]); + } + break; -void io_seproxyhal_handle_usb_ep_xfer_event(void) { - uint8_t epnum; - - epnum = G_io_seproxyhal_spi_buffer[3] & 0x7F; - - switch(G_io_seproxyhal_spi_buffer[4]) { - /* This event is received when a new SETUP token had been received on a control endpoint */ - case SEPROXYHAL_TAG_USB_EP_XFER_SETUP: - // assume length of setup packet, and that it is on endpoint 0 - USBD_LL_SetupStage(&USBD_Device, &G_io_seproxyhal_spi_buffer[6]); - break; - - /* This event is received after the prepare data packet has been flushed to the usb host */ - case SEPROXYHAL_TAG_USB_EP_XFER_IN: - if (epnum < IO_USB_MAX_ENDPOINTS) { - // discard ep timeout as we received the sent packet confirmation - G_io_app.usb_ep_timeouts[epnum].timeout = 0; - // propagate sending ack of the data - USBD_LL_DataInStage(&USBD_Device, epnum, &G_io_seproxyhal_spi_buffer[6]); - } - break; - - /* This event is received when a new DATA token is received on an endpoint */ - case SEPROXYHAL_TAG_USB_EP_XFER_OUT: - if (epnum < IO_USB_MAX_ENDPOINTS) { - // saved just in case it is needed ... + /* This event is received when a new DATA token is received on an endpoint */ + case SEPROXYHAL_TAG_USB_EP_XFER_OUT: + if (epnum < IO_USB_MAX_ENDPOINTS) { + // saved just in case it is needed ... #if IO_SEPROXYHAL_BUFFER_SIZE_B - 6 >= 256 - G_io_app.usb_ep_xfer_len[epnum] = G_io_seproxyhal_spi_buffer[5]; + G_io_app.usb_ep_xfer_len[epnum] = G_io_seproxyhal_spi_buffer[5]; #else - G_io_app.usb_ep_xfer_len[epnum] = MIN(G_io_seproxyhal_spi_buffer[5], IO_SEPROXYHAL_BUFFER_SIZE_B - 6); + G_io_app.usb_ep_xfer_len[epnum] + = MIN(G_io_seproxyhal_spi_buffer[5], IO_SEPROXYHAL_BUFFER_SIZE_B - 6); #endif - // prepare reception - USBD_LL_DataOutStage(&USBD_Device, epnum, &G_io_seproxyhal_spi_buffer[6], NULL); - } - break; - } + // prepare reception + USBD_LL_DataOutStage(&USBD_Device, epnum, &G_io_seproxyhal_spi_buffer[6], NULL); + } + break; + } } #else -//no usb lib: X86 for example +// no usb lib: X86 for example -void io_seproxyhal_handle_usb_event(void) { -} -void io_seproxyhal_handle_usb_ep_xfer_event(void) { -} - -#endif // HAVE_L4_USBLIB +void io_seproxyhal_handle_usb_event(void) {} +void io_seproxyhal_handle_usb_ep_xfer_event(void) {} +#endif // HAVE_L4_USBLIB #ifdef HAVE_WEBUSB -void io_usb_send_apdu_data_ep0x83(unsigned char* buffer, unsigned short length) { - // wait for 20 events before hanging up and timeout (~2 seconds of timeout) - io_usb_send_ep(0x83, buffer, length, 20); +void io_usb_send_apdu_data_ep0x83(unsigned char *buffer, unsigned short length) +{ + // wait for 20 events before hanging up and timeout (~2 seconds of timeout) + io_usb_send_ep(0x83, buffer, length, 20); } -#endif // HAVE_WEBUSB +#endif // HAVE_WEBUSB -#endif // HAVE_IO_USB +#endif // HAVE_IO_USB -void io_seproxyhal_handle_capdu_event(void) { - if (G_io_app.apdu_state == APDU_IDLE) { - size_t max = MIN(sizeof(G_io_apdu_buffer)-3, sizeof(G_io_seproxyhal_spi_buffer)-3); - size_t size = U2BE(G_io_seproxyhal_spi_buffer, 1); - - G_io_app.apdu_media = IO_APDU_MEDIA_RAW; // for application code - G_io_app.apdu_state = APDU_RAW; // for next call to io_exchange - G_io_app.apdu_length = MIN(size, max); - // copy apdu to apdu buffer - memcpy(G_io_apdu_buffer, G_io_seproxyhal_spi_buffer+3, G_io_app.apdu_length); - } +void io_seproxyhal_handle_capdu_event(void) +{ + if (G_io_app.apdu_state == APDU_IDLE) { + size_t max = MIN(sizeof(G_io_apdu_buffer) - 3, sizeof(G_io_seproxyhal_spi_buffer) - 3); + size_t size = U2BE(G_io_seproxyhal_spi_buffer, 1); + + G_io_app.apdu_media = IO_APDU_MEDIA_RAW; // for application code + G_io_app.apdu_state = APDU_RAW; // for next call to io_exchange + G_io_app.apdu_length = MIN(size, max); + // copy apdu to apdu buffer + memcpy(G_io_apdu_buffer, G_io_seproxyhal_spi_buffer + 3, G_io_app.apdu_length); + } } #ifdef HAVE_NFC -void io_seproxyhal_handle_nfc_recv_event(void) { - G_io_app.apdu_media = IO_APDU_MEDIA_NFC; - G_io_app.apdu_state = APDU_NFC; - G_io_app.apdu_length = ((G_io_seproxyhal_spi_buffer[1] << 8) & 0xFF00) | (G_io_seproxyhal_spi_buffer[2] & 0x00FF); - memcpy(G_io_apdu_buffer, &G_io_seproxyhal_spi_buffer[3], G_io_app.apdu_length); +void io_seproxyhal_handle_nfc_recv_event(void) +{ + G_io_app.apdu_media = IO_APDU_MEDIA_NFC; + G_io_app.apdu_state = APDU_NFC; + G_io_app.apdu_length = ((G_io_seproxyhal_spi_buffer[1] << 8) & 0xFF00) + | (G_io_seproxyhal_spi_buffer[2] & 0x00FF); + memcpy(G_io_apdu_buffer, &G_io_seproxyhal_spi_buffer[3], G_io_app.apdu_length); } #endif -unsigned int io_seproxyhal_handle_event(void) { +unsigned int io_seproxyhal_handle_event(void) +{ #if defined(HAVE_IO_USB) || defined(HAVE_BLE) - unsigned int rx_len = U2BE(G_io_seproxyhal_spi_buffer, 1); + unsigned int rx_len = U2BE(G_io_seproxyhal_spi_buffer, 1); #endif - switch(G_io_seproxyhal_spi_buffer[0]) { - #ifdef HAVE_IO_USB - case SEPROXYHAL_TAG_USB_EVENT: - if (rx_len != 1) { - return 0; - } - io_seproxyhal_handle_usb_event(); - return 1; + switch (G_io_seproxyhal_spi_buffer[0]) { +#ifdef HAVE_IO_USB + case SEPROXYHAL_TAG_USB_EVENT: + if (rx_len != 1) { + return 0; + } + io_seproxyhal_handle_usb_event(); + return 1; - case SEPROXYHAL_TAG_USB_EP_XFER_EVENT: - if (rx_len < 3) { - // error ! - return 0; - } - io_seproxyhal_handle_usb_ep_xfer_event(); - return 1; - #endif // HAVE_IO_USB - - #ifdef HAVE_BLE - case SEPROXYHAL_TAG_BLE_RECV_EVENT: - LEDGER_BLE_receive(); - return 1; - #endif // HAVE_BLE - - #ifdef HAVE_NFC - case SEPROXYHAL_TAG_NFC_APDU_EVENT: - io_seproxyhal_handle_nfc_recv_event(); - return 1; - #endif - - case SEPROXYHAL_TAG_UX_EVENT: - switch (G_io_seproxyhal_spi_buffer[3]) { + case SEPROXYHAL_TAG_USB_EP_XFER_EVENT: + if (rx_len < 3) { + // error ! + return 0; + } + io_seproxyhal_handle_usb_ep_xfer_event(); + return 1; +#endif // HAVE_IO_USB + +#ifdef HAVE_BLE + case SEPROXYHAL_TAG_BLE_RECV_EVENT: + LEDGER_BLE_receive(); + return 1; +#endif // HAVE_BLE + +#ifdef HAVE_NFC + case SEPROXYHAL_TAG_NFC_APDU_EVENT: + io_seproxyhal_handle_nfc_recv_event(); + return 1; +#endif + case SEPROXYHAL_TAG_UX_EVENT: + switch (G_io_seproxyhal_spi_buffer[3]) { #ifdef HAVE_BLE - case SEPROXYHAL_TAG_UX_CMD_BLE_DISABLE_ADV: - LEDGER_BLE_enable_advertising(0); - return 1; - break; - - case SEPROXYHAL_TAG_UX_CMD_BLE_ENABLE_ADV: - LEDGER_BLE_enable_advertising(1); - return 1; - break; - - case SEPROXYHAL_TAG_UX_CMD_BLE_RESET_PAIRINGS: - LEDGER_BLE_reset_pairings(); - return 1; - break; - - case SEPROXYHAL_TAG_UX_CMD_BLE_NAME_CHANGED: - // Restart advertising - G_io_app.name_changed = 1; - io_seph_ble_enable(0); - break; -#endif // HAVE_BLE + case SEPROXYHAL_TAG_UX_CMD_BLE_DISABLE_ADV: + LEDGER_BLE_enable_advertising(0); + return 1; + break; + + case SEPROXYHAL_TAG_UX_CMD_BLE_ENABLE_ADV: + LEDGER_BLE_enable_advertising(1); + return 1; + break; + + case SEPROXYHAL_TAG_UX_CMD_BLE_RESET_PAIRINGS: + LEDGER_BLE_reset_pairings(); + return 1; + break; + + case SEPROXYHAL_TAG_UX_CMD_BLE_NAME_CHANGED: + // Restart advertising + G_io_app.name_changed = 1; + io_seph_ble_enable(0); + break; +#endif // HAVE_BLE #if !defined(HAVE_BOLOS) && defined(HAVE_BAGL) - case SEPROXYHAL_TAG_UX_CMD_REDISPLAY: - ux_stack_redisplay(); - return 1; - break; -#endif // HAVE_BOLOS - - default: - return io_event(CHANNEL_SPI); - break; - } - break; - - case SEPROXYHAL_TAG_CAPDU_EVENT: - io_seproxyhal_handle_capdu_event(); - return 1; - - // ask the user if not processed here - case SEPROXYHAL_TAG_TICKER_EVENT: - // process ticker events to timeout the IO transfers, and forward to the user io_event function too - G_io_app.ms += 100; // value is by default, don't change the ticker configuration + case SEPROXYHAL_TAG_UX_CMD_REDISPLAY: + ux_stack_redisplay(); + return 1; + break; +#endif // HAVE_BOLOS + + default: + return io_event(CHANNEL_SPI); + break; + } + break; + + case SEPROXYHAL_TAG_CAPDU_EVENT: + io_seproxyhal_handle_capdu_event(); + return 1; + + // ask the user if not processed here + case SEPROXYHAL_TAG_TICKER_EVENT: + // process ticker events to timeout the IO transfers, and forward to the user io_event + // function too + G_io_app.ms += 100; // value is by default, don't change the ticker configuration #ifdef HAVE_IO_USB - { - unsigned int i = IO_USB_MAX_ENDPOINTS; - while(i--) { - if (G_io_app.usb_ep_timeouts[i].timeout) { - G_io_app.usb_ep_timeouts[i].timeout-=MIN(G_io_app.usb_ep_timeouts[i].timeout, 100); - if (!G_io_app.usb_ep_timeouts[i].timeout) { - // timeout ! - G_io_app.apdu_state = APDU_IDLE; - THROW(EXCEPTION_IO_RESET); + { + unsigned int i = IO_USB_MAX_ENDPOINTS; + while (i--) { + if (G_io_app.usb_ep_timeouts[i].timeout) { + G_io_app.usb_ep_timeouts[i].timeout + -= MIN(G_io_app.usb_ep_timeouts[i].timeout, 100); + if (!G_io_app.usb_ep_timeouts[i].timeout) { + // timeout ! + G_io_app.apdu_state = APDU_IDLE; + THROW(EXCEPTION_IO_RESET); + } + } + } } - } - } - } -#endif // HAVE_IO_USB +#endif // HAVE_IO_USB #ifdef HAVE_BLE_APDU - { - if (G_io_app.ble_xfer_timeout) { - G_io_app.ble_xfer_timeout -= MIN(G_io_app.ble_xfer_timeout, 100); - if (!G_io_app.ble_xfer_timeout) { - G_io_app.apdu_state = APDU_IDLE; - THROW(EXCEPTION_IO_RESET); - } - } - } -#endif // HAVE_BLE_APDU - FALL_THROUGH; - // no break is intentional - default: - return io_event(CHANNEL_SPI); - } - // defaultly return as not processed - return 0; + { + if (G_io_app.ble_xfer_timeout) { + G_io_app.ble_xfer_timeout -= MIN(G_io_app.ble_xfer_timeout, 100); + if (!G_io_app.ble_xfer_timeout) { + G_io_app.apdu_state = APDU_IDLE; + THROW(EXCEPTION_IO_RESET); + } + } + } +#endif // HAVE_BLE_APDU + FALL_THROUGH; + // no break is intentional + default: + return io_event(CHANNEL_SPI); + } + // defaultly return as not processed + return 0; } -//#define DEBUG_APDU +// #define DEBUG_APDU #ifdef DEBUG_APDU volatile unsigned int debug_apdus_offset; -const char debug_apdus[] = { - 5, 0xE0, 0x40, 0x00, 0x00, 0x00, - //9, 0xe0, 0x22, 0x00, 0x00, 0x04, 0x31, 0x32, 0x33, 0x34, +const char debug_apdus[] = { + 5, + 0xE0, + 0x40, + 0x00, + 0x00, + 0x00, + // 9, 0xe0, 0x22, 0x00, 0x00, 0x04, 0x31, 0x32, 0x33, 0x34, }; -#endif // DEBUG_APDU +#endif // DEBUG_APDU #ifdef HAVE_BOLOS_APP_STACK_CANARY #define APP_STACK_CANARY_MAGIC 0xDEAD0031 extern unsigned int app_stack_canary; -#endif // HAVE_BOLOS_APP_STACK_CANARY +#endif // HAVE_BOLOS_APP_STACK_CANARY #if (!defined(HAVE_BOLOS) && defined(HAVE_MCU_PROTECT)) -static const unsigned char seph_io_mcu_protect[]= { - SEPROXYHAL_TAG_MCU, - 0, - 1, - SEPROXYHAL_TAG_MCU_TYPE_PROTECT, +static const unsigned char seph_io_mcu_protect[] = { + SEPROXYHAL_TAG_MCU, + 0, + 1, + SEPROXYHAL_TAG_MCU_TYPE_PROTECT, }; -#endif // (!defined(HAVE_BOLOS) && defined(HAVE_MCU_PROTECT)) +#endif // (!defined(HAVE_BOLOS) && defined(HAVE_MCU_PROTECT)) -void io_seproxyhal_init(void) { +void io_seproxyhal_init(void) +{ #ifndef HAVE_BOLOS - // Enforce OS compatibility - check_api_level(CX_COMPAT_APILEVEL); + // Enforce OS compatibility + check_api_level(CX_COMPAT_APILEVEL); #ifdef HAVE_MCU_PROTECT - // engage RDP2 on MCU - io_seproxyhal_spi_send(seph_io_mcu_protect, sizeof(seph_io_mcu_protect)); -#endif // HAVE_MCU_PROTECT -#endif // HAVE_BOLOS + // engage RDP2 on MCU + io_seproxyhal_spi_send(seph_io_mcu_protect, sizeof(seph_io_mcu_protect)); +#endif // HAVE_MCU_PROTECT +#endif // HAVE_BOLOS #ifdef HAVE_BOLOS_APP_STACK_CANARY - app_stack_canary = APP_STACK_CANARY_MAGIC; -#endif // HAVE_BOLOS_APP_STACK_CANARY + app_stack_canary = APP_STACK_CANARY_MAGIC; +#endif // HAVE_BOLOS_APP_STACK_CANARY - // wipe the io structure before it's used + // wipe the io structure before it's used #ifdef HAVE_BLE - unsigned int plane = G_io_app.plane_mode; -#endif // HAVE_BLE - memset(&G_io_app, 0, sizeof(G_io_app)); + unsigned int plane = G_io_app.plane_mode; +#endif // HAVE_BLE + memset(&G_io_app, 0, sizeof(G_io_app)); #ifdef HAVE_BLE - G_io_app.plane_mode = plane; -#endif // HAVE_BLE + G_io_app.plane_mode = plane; +#endif // HAVE_BLE - G_io_app.apdu_state = APDU_IDLE; - G_io_app.apdu_length = 0; - G_io_app.apdu_media = IO_APDU_MEDIA_NONE; + G_io_app.apdu_state = APDU_IDLE; + G_io_app.apdu_length = 0; + G_io_app.apdu_media = IO_APDU_MEDIA_NONE; - G_io_app.ms = 0; + G_io_app.ms = 0; - #ifdef DEBUG_APDU - debug_apdus_offset = 0; - #endif // DEBUG_APDU +#ifdef DEBUG_APDU + debug_apdus_offset = 0; +#endif // DEBUG_APDU - #ifdef HAVE_USB_APDU - io_usb_hid_init(); - #endif // HAVE_USB_APDU +#ifdef HAVE_USB_APDU + io_usb_hid_init(); +#endif // HAVE_USB_APDU #ifdef HAVE_BAGL - io_seproxyhal_init_ux(); - io_seproxyhal_init_button(); + io_seproxyhal_init_ux(); + io_seproxyhal_init_button(); #endif #if !defined(HAVE_BOLOS) && defined(HAVE_PENDING_REVIEW_SCREEN) - check_audited_app(); -#endif // !defined(HAVE_BOLOS) && defined(HAVE_PENDING_REVIEW_SCREEN) + check_audited_app(); +#endif // !defined(HAVE_BOLOS) && defined(HAVE_PENDING_REVIEW_SCREEN) } #ifdef HAVE_PIEZO_SOUND -void io_seproxyhal_play_tune(tune_index_e tune_index) { - uint8_t buffer[4]; - if(tune_index >= NB_TUNES) { - return; - } - - uint32_t sound_setting = os_setting_get(OS_SETTING_PIEZO_SOUND, NULL, 0); - - if ((!IS_NOTIF_ENABLED(sound_setting)) && (tune_index < TUNE_TAP_CASUAL)) { - return; - } - - if ((!IS_TAP_ENABLED(sound_setting)) && (tune_index >= TUNE_TAP_CASUAL)) { - return; - } - - if (io_seproxyhal_spi_is_status_sent()) { - io_seproxyhal_spi_recv(G_io_seproxyhal_spi_buffer, sizeof(G_io_seproxyhal_spi_buffer), 0); - } - - buffer[0] = SEPROXYHAL_TAG_PLAY_TUNE; - buffer[1] = 0; - buffer[2] = 1; - buffer[3] = (uint8_t) tune_index; - io_seproxyhal_spi_send(buffer, 4); +void io_seproxyhal_play_tune(tune_index_e tune_index) +{ + uint8_t buffer[4]; + if (tune_index >= NB_TUNES) { + return; + } + + uint32_t sound_setting = os_setting_get(OS_SETTING_PIEZO_SOUND, NULL, 0); + + if ((!IS_NOTIF_ENABLED(sound_setting)) && (tune_index < TUNE_TAP_CASUAL)) { + return; + } + + if ((!IS_TAP_ENABLED(sound_setting)) && (tune_index >= TUNE_TAP_CASUAL)) { + return; + } + + if (io_seproxyhal_spi_is_status_sent()) { + io_seproxyhal_spi_recv(G_io_seproxyhal_spi_buffer, sizeof(G_io_seproxyhal_spi_buffer), 0); + } + + buffer[0] = SEPROXYHAL_TAG_PLAY_TUNE; + buffer[1] = 0; + buffer[2] = 1; + buffer[3] = (uint8_t) tune_index; + io_seproxyhal_spi_send(buffer, 4); } -#endif // HAVE_PIEZO_SOUND +#endif // HAVE_PIEZO_SOUND #ifdef HAVE_NFC #ifdef HAVE_NDEF_SUPPORT - #include "nfc_ndef.h" +#include "nfc_ndef.h" #endif #ifdef HAVE_NDEF_SUPPORT @@ -476,42 +490,54 @@ void io_seproxyhal_play_tune(tune_index_e tune_index) { * @brief Send a SEPH message to MCU to init NFC * * @param ndef_message NDEF message to program into tag, can be NULL (ie no message in tag) - * @param async set to true, if nfc_init is performed while an NFC transfer is ongoing, set to false otherwise - * @param forceInit set to true, to force NFC init even if NFC is de-activated in settings, false otherwise + * @param async set to true, if nfc_init is performed while an NFC transfer is ongoing, set to false + * otherwise + * @param forceInit set to true, to force NFC init even if NFC is de-activated in settings, false + * otherwise */ -void io_seproxyhal_nfc_init(ndef_struct_t *ndef_message, bool async, bool forceInit) { - uint8_t buffer[5]; - uint16_t total_length = 0; - uint8_t is_nfc_enabled = forceInit?1:(os_setting_get(OS_SETTING_FEATURES, NULL, 0)&OS_SETTING_FEATURES_NFC_ENABLED); - buffer[0] = SEPROXYHAL_TAG_NFC_INIT; - // Fill length offsets 1 and 2 later when text length is known - buffer[3] = is_nfc_enabled; - buffer[4] = (uint8_t) async; - total_length += 2; - if (ndef_message != NULL) { - total_length += sizeof(ndef_struct_t); - memcpy(G_io_seproxyhal_spi_buffer, ndef_message, sizeof(ndef_struct_t)); - } - else { - total_length += os_setting_get(OS_SETTING_NFC_TAG_CONTENT, (uint8_t*)G_io_seproxyhal_spi_buffer, sizeof(ndef_struct_t)); - } - buffer[1] = (total_length & 0xFF00) >> 8; - buffer[2] = total_length & 0x00FF; - io_seproxyhal_spi_send(buffer, 5); - io_seproxyhal_spi_send(G_io_seproxyhal_spi_buffer, total_length-2); +void io_seproxyhal_nfc_init(ndef_struct_t *ndef_message, bool async, bool forceInit) +{ + uint8_t buffer[5]; + uint16_t total_length = 0; + uint8_t is_nfc_enabled + = forceInit + ? 1 + : (os_setting_get(OS_SETTING_FEATURES, NULL, 0) & OS_SETTING_FEATURES_NFC_ENABLED); + buffer[0] = SEPROXYHAL_TAG_NFC_INIT; + // Fill length offsets 1 and 2 later when text length is known + buffer[3] = is_nfc_enabled; + buffer[4] = (uint8_t) async; + total_length += 2; + if (ndef_message != NULL) { + total_length += sizeof(ndef_struct_t); + memcpy(G_io_seproxyhal_spi_buffer, ndef_message, sizeof(ndef_struct_t)); + } + else { + total_length += os_setting_get(OS_SETTING_NFC_TAG_CONTENT, + (uint8_t *) G_io_seproxyhal_spi_buffer, + sizeof(ndef_struct_t)); + } + buffer[1] = (total_length & 0xFF00) >> 8; + buffer[2] = total_length & 0x00FF; + io_seproxyhal_spi_send(buffer, 5); + io_seproxyhal_spi_send(G_io_seproxyhal_spi_buffer, total_length - 2); } -#else // ! HAVE_NDEF_SUPPORT -void io_seproxyhal_nfc_init(bool forceInit) { - uint8_t buffer[4]; - uint8_t is_nfc_enabled = forceInit?1:(os_setting_get(OS_SETTING_FEATURES, NULL, 0)&OS_SETTING_FEATURES_NFC_ENABLED); - buffer[0] = SEPROXYHAL_TAG_NFC_INIT; - buffer[1] = 0; - buffer[2] = 1; - buffer[3] = is_nfc_enabled; - io_seproxyhal_spi_send(buffer, 4); +#else // ! HAVE_NDEF_SUPPORT +void io_seproxyhal_nfc_init(bool forceInit) +{ + uint8_t buffer[4]; + uint8_t is_nfc_enabled + = forceInit + ? 1 + : (os_setting_get(OS_SETTING_FEATURES, NULL, 0) & OS_SETTING_FEATURES_NFC_ENABLED); + buffer[0] = SEPROXYHAL_TAG_NFC_INIT; + buffer[1] = 0; + buffer[2] = 1; + buffer[3] = is_nfc_enabled; + io_seproxyhal_spi_send(buffer, 4); } -#endif // HAVE_NDEF_SUPPORT -#endif // HAVE_NFC +#endif // HAVE_NDEF_SUPPORT +#endif // HAVE_NFC #ifdef HAVE_SE_TOUCH #ifdef HAVE_TOUCH_READ_DEBUG_DATA_SYSCALL @@ -521,8 +547,9 @@ void io_seproxyhal_nfc_init(bool forceInit) { * @param sensi_data Pointer to the buffer to store sensi data * @return BOLOS_TRUE/BOLOS_FALSE */ -bolos_bool_t io_seproxyhal_touch_debug_read_sensi(uint8_t * sensi_data) { - return touch_switch_debug_mode_and_read(TOUCH_DEBUG_READ_RAW_DATA, sensi_data); +bolos_bool_t io_seproxyhal_touch_debug_read_sensi(uint8_t *sensi_data) +{ + return touch_switch_debug_mode_and_read(TOUCH_DEBUG_READ_RAW_DATA, sensi_data); } /** @@ -531,8 +558,9 @@ bolos_bool_t io_seproxyhal_touch_debug_read_sensi(uint8_t * sensi_data) { * @param diff_data Pointer to the buffer to store diff data * @return BOLOS_TRUE/BOLOS_FALSE */ -bolos_bool_t io_seproxyhal_touch_debug_read_diff_data(uint8_t *diff_data) { - return touch_switch_debug_mode_and_read(TOUCH_DEBUG_READ_DIFF_DATA, diff_data); +bolos_bool_t io_seproxyhal_touch_debug_read_diff_data(uint8_t *diff_data) +{ + return touch_switch_debug_mode_and_read(TOUCH_DEBUG_READ_DIFF_DATA, diff_data); } /** @@ -541,413 +569,455 @@ bolos_bool_t io_seproxyhal_touch_debug_read_diff_data(uint8_t *diff_data) { * @param None * @return BOLOS_TRUE/BOLOS_FALSE */ -bolos_bool_t io_seproxyhal_touch_debug_end(void) { - return touch_switch_debug_mode_and_read(TOUCH_DEBUG_END, NULL); +bolos_bool_t io_seproxyhal_touch_debug_end(void) +{ + return touch_switch_debug_mode_and_read(TOUCH_DEBUG_END, NULL); } #endif #endif #ifdef HAVE_BAGL -void io_seproxyhal_init_ux(void) { -} +void io_seproxyhal_init_ux(void) {} -void io_seproxyhal_init_button(void) { - // no button push so far - G_ux_os.button_mask = 0; - G_ux_os.button_same_mask_counter = 0; +void io_seproxyhal_init_button(void) +{ + // no button push so far + G_ux_os.button_mask = 0; + G_ux_os.button_same_mask_counter = 0; } -void io_seproxyhal_display_bitmap(int x, int y, unsigned int w, unsigned int h, unsigned int* color_index, unsigned int bit_per_pixel, unsigned char* bitmap) { - // component type = ICON - // component icon id = 0 - // => bitmap transmitted - if (w && h) { - bagl_component_t c; - bagl_icon_details_t d; - memset(&c, 0, sizeof(c)); - c.type = BAGL_ICON; - c.x = x; - c.y = y; - c.width = w; - c.height = h; - // done by memset // c.icon_id = 0; - d.width = w; - d.height = h; - d.bpp = bit_per_pixel; - d.colors = color_index; - d.bitmap = bitmap; - - io_seproxyhal_display_icon(&c, &d); - /* - // color index size - h = ((1<>8; - G_io_seproxyhal_spi_buffer[2] = length; - io_seproxyhal_spi_send(G_io_seproxyhal_spi_buffer, 3); - io_seproxyhal_spi_send((unsigned char*)&c, sizeof(bagl_component_t)); - G_io_seproxyhal_spi_buffer[0] = bit_per_pixel; - io_seproxyhal_spi_send(G_io_seproxyhal_spi_buffer, 1); - io_seproxyhal_spi_send((unsigned char*)color_index, h); - io_seproxyhal_spi_send(bitmap, w); - */ - } +void io_seproxyhal_display_bitmap(int x, + int y, + unsigned int w, + unsigned int h, + unsigned int *color_index, + unsigned int bit_per_pixel, + unsigned char *bitmap) +{ + // component type = ICON + // component icon id = 0 + // => bitmap transmitted + if (w && h) { + bagl_component_t c; + bagl_icon_details_t d; + memset(&c, 0, sizeof(c)); + c.type = BAGL_ICON; + c.x = x; + c.y = y; + c.width = w; + c.height = h; + // done by memset // c.icon_id = 0; + d.width = w; + d.height = h; + d.bpp = bit_per_pixel; + d.colors = color_index; + d.bitmap = bitmap; + + io_seproxyhal_display_icon(&c, &d); + /* + // color index size + h = ((1<>8; + G_io_seproxyhal_spi_buffer[2] = length; + io_seproxyhal_spi_send(G_io_seproxyhal_spi_buffer, 3); + io_seproxyhal_spi_send((unsigned char*)&c, sizeof(bagl_component_t)); + G_io_seproxyhal_spi_buffer[0] = bit_per_pixel; + io_seproxyhal_spi_send(G_io_seproxyhal_spi_buffer, 1); + io_seproxyhal_spi_send((unsigned char*)color_index, h); + io_seproxyhal_spi_send(bitmap, w); + */ + } } #ifdef SEPROXYHAL_TAG_SCREEN_DISPLAY_RAW_STATUS -unsigned int io_seproxyhal_display_icon_header_and_colors(const bagl_component_t* icon_component, const bagl_icon_details_t* icon_details, unsigned int* icon_len) { - unsigned int len; - - struct display_raw_s { - struct { - struct { - unsigned char tag; - unsigned char len[2]; - } seph; - unsigned char type; - } header; - union { - short val; - char b[2]; - } x; - union { - short val; - char b[2]; - } y; - union { - unsigned short val; - char b[2]; - } w; - union { - unsigned short val; - char b[2]; - } h; - unsigned char bpp; - } __attribute__((packed)) raw; - - raw.header.seph.tag = SEPROXYHAL_TAG_SCREEN_DISPLAY_RAW_STATUS; - raw.header.type = SEPROXYHAL_TAG_SCREEN_DISPLAY_RAW_STATUS_START; - raw.x.val = icon_component->x; - raw.y.val = icon_component->y; - raw.w.val = icon_component->width; - raw.h.val = icon_component->height; - raw.bpp = icon_details->bpp; - - - *icon_len = raw.w.val*raw.h.val*raw.bpp/8 + (((raw.w.val*raw.h.val*raw.bpp)%8)?1:0); - - // optional, don't send too much on a single packet for MCU to receive it. when stream mode will be on, this will be useless - // min of remaining space in the packet vs. total icon size + color index size - len = MIN(sizeof(G_io_seproxyhal_spi_buffer) - sizeof(raw), *icon_len + (1<> 8; - raw.header.seph.len[1] = (len + sizeof(raw) - sizeof(raw.header.seph)); - - // swap endianness of coordinates (make it big endian) - SWAP(raw.x.b[0], raw.x.b[1]); - SWAP(raw.y.b[0], raw.y.b[1]); - SWAP(raw.w.b[0], raw.w.b[1]); - SWAP(raw.h.b[0], raw.h.b[1]); - - io_seproxyhal_spi_send((unsigned char*)&raw, sizeof(raw)); - io_seproxyhal_spi_send((const uint8_t *) PIC(icon_details->colors), (1<x; + raw.y.val = icon_component->y; + raw.w.val = icon_component->width; + raw.h.val = icon_component->height; + raw.bpp = icon_details->bpp; + + *icon_len + = raw.w.val * raw.h.val * raw.bpp / 8 + (((raw.w.val * raw.h.val * raw.bpp) % 8) ? 1 : 0); + + // optional, don't send too much on a single packet for MCU to receive it. when stream mode will + // be on, this will be useless min of remaining space in the packet vs. total icon size + color + // index size + len = MIN(sizeof(G_io_seproxyhal_spi_buffer) - sizeof(raw), *icon_len + (1 << raw.bpp) * 4); + + // sizeof packet + raw.header.seph.len[0] = (len + sizeof(raw) - sizeof(raw.header.seph)) >> 8; + raw.header.seph.len[1] = (len + sizeof(raw) - sizeof(raw.header.seph)); + + // swap endianness of coordinates (make it big endian) + SWAP(raw.x.b[0], raw.x.b[1]); + SWAP(raw.y.b[0], raw.y.b[1]); + SWAP(raw.w.b[0], raw.w.b[1]); + SWAP(raw.h.b[0], raw.h.b[1]); + + io_seproxyhal_spi_send((unsigned char *) &raw, sizeof(raw)); + io_seproxyhal_spi_send((const uint8_t *) PIC(icon_details->colors), (1 << raw.bpp) * 4); + len -= (1 << raw.bpp) * 4; + + // remaining length of bitmap bits to be displayed + return len; } -#endif // SEPROXYHAL_TAG_SCREEN_DISPLAY_RAW_STATUS +#endif // SEPROXYHAL_TAG_SCREEN_DISPLAY_RAW_STATUS -void io_seproxyhal_display_icon(const bagl_component_t* icon_component, const bagl_icon_details_t* icon_det) { - bagl_component_t icon_component_mod; - const bagl_icon_details_t* icon_details = (const bagl_icon_details_t *)PIC(icon_det); +void io_seproxyhal_display_icon(const bagl_component_t *icon_component, + const bagl_icon_details_t *icon_det) +{ + bagl_component_t icon_component_mod; + const bagl_icon_details_t *icon_details = (const bagl_icon_details_t *) PIC(icon_det); - if (icon_details && icon_details->bitmap) { - // ensure not being out of bounds in the icon component against the declared icon real size - memcpy(&icon_component_mod, PIC(icon_component), sizeof(bagl_component_t)); - icon_component_mod.width = icon_details->width; - icon_component_mod.height = icon_details->height; - icon_component = &icon_component_mod; + if (icon_details && icon_details->bitmap) { + // ensure not being out of bounds in the icon component against the declared icon real size + memcpy(&icon_component_mod, PIC(icon_component), sizeof(bagl_component_t)); + icon_component_mod.width = icon_details->width; + icon_component_mod.height = icon_details->height; + icon_component = &icon_component_mod; #ifdef SEPROXYHAL_TAG_SCREEN_DISPLAY_RAW_STATUS - unsigned int len; - unsigned int icon_len; - unsigned int icon_off=0; - - len = io_seproxyhal_display_icon_header_and_colors(icon_component, icon_details, &icon_len); - io_seproxyhal_spi_send(PIC(icon_details->bitmap), len); - // advance in the bitmap to be transmitted - icon_len -= len; - icon_off += len; - - // still some bitmap data to transmit - while(icon_len) { - // wait displayed event - io_seproxyhal_spi_recv(G_io_seproxyhal_spi_buffer, sizeof(G_io_seproxyhal_spi_buffer), 0); - - G_io_seproxyhal_spi_buffer[0] = SEPROXYHAL_TAG_SCREEN_DISPLAY_RAW_STATUS; - G_io_seproxyhal_spi_buffer[3] = SEPROXYHAL_TAG_SCREEN_DISPLAY_RAW_STATUS_CONT; - - len = MIN((sizeof(G_io_seproxyhal_spi_buffer) - 4), icon_len); - G_io_seproxyhal_spi_buffer[1] = (len+1)>>8; - G_io_seproxyhal_spi_buffer[2] = (len+1); - io_seproxyhal_spi_send(G_io_seproxyhal_spi_buffer, 4); - io_seproxyhal_spi_send(PIC(icon_details->bitmap)+icon_off, len); - - icon_len -= len; - icon_off += len; - } -#else // !SEPROXYHAL_TAG_SCREEN_DISPLAY_RAW_STATUS + unsigned int len; + unsigned int icon_len; + unsigned int icon_off = 0; + + len = io_seproxyhal_display_icon_header_and_colors(icon_component, icon_details, &icon_len); + io_seproxyhal_spi_send(PIC(icon_details->bitmap), len); + // advance in the bitmap to be transmitted + icon_len -= len; + icon_off += len; + + // still some bitmap data to transmit + while (icon_len) { + // wait displayed event + io_seproxyhal_spi_recv( + G_io_seproxyhal_spi_buffer, sizeof(G_io_seproxyhal_spi_buffer), 0); + + G_io_seproxyhal_spi_buffer[0] = SEPROXYHAL_TAG_SCREEN_DISPLAY_RAW_STATUS; + G_io_seproxyhal_spi_buffer[3] = SEPROXYHAL_TAG_SCREEN_DISPLAY_RAW_STATUS_CONT; + + len = MIN((sizeof(G_io_seproxyhal_spi_buffer) - 4), icon_len); + G_io_seproxyhal_spi_buffer[1] = (len + 1) >> 8; + G_io_seproxyhal_spi_buffer[2] = (len + 1); + io_seproxyhal_spi_send(G_io_seproxyhal_spi_buffer, 4); + io_seproxyhal_spi_send(PIC(icon_details->bitmap) + icon_off, len); + + icon_len -= len; + icon_off += len; + } +#else // !SEPROXYHAL_TAG_SCREEN_DISPLAY_RAW_STATUS #ifdef HAVE_SE_SCREEN - bagl_draw_glyph(&icon_component_mod, icon_details); -#endif // HAVE_SE_SCREEN + bagl_draw_glyph(&icon_component_mod, icon_details); +#endif // HAVE_SE_SCREEN #if !defined(HAVE_SE_SCREEN) || (defined(HAVE_SE_SCREEN) && defined(HAVE_PRINTF)) - if (io_seproxyhal_spi_is_status_sent()) { - return; - } - // color index size - unsigned int h = (1<<(icon_details->bpp))*sizeof(unsigned int); - // bitmap size - unsigned int w = ((icon_component->width*icon_component->height*icon_details->bpp)/8)+((icon_component->width*icon_component->height*icon_details->bpp)%8?1:0); - unsigned short length = sizeof(bagl_component_t) - +1 /* bpp */ - +h /* color index */ - +w; /* image bitmap size */ - if (length > (sizeof(G_io_seproxyhal_spi_buffer)-4)) { + if (io_seproxyhal_spi_is_status_sent()) { + return; + } + // color index size + unsigned int h = (1 << (icon_details->bpp)) * sizeof(unsigned int); + // bitmap size + unsigned int w + = ((icon_component->width * icon_component->height * icon_details->bpp) / 8) + + ((icon_component->width * icon_component->height * icon_details->bpp) % 8 ? 1 : 0); + unsigned short length = sizeof(bagl_component_t) + 1 /* bpp */ + + h /* color index */ + + w; /* image bitmap size */ + if (length > (sizeof(G_io_seproxyhal_spi_buffer) - 4)) { #if defined(HAVE_PRINTF) - PRINTF("ERROR: Inside io_seproxyhal_display_icon, icon size (%d) is too big for the buffer (%d-4)! (bitmap=0x%x, width=%d, height=%d, bpp=%d)\n", length, sizeof(G_io_seproxyhal_spi_buffer), icon_details->bitmap, icon_details->width, icon_details->height, icon_details->bpp); -#endif //defined(HAVE_PRINTF) - return; - } - G_io_seproxyhal_spi_buffer[0] = SEPROXYHAL_TAG_SCREEN_DISPLAY_STATUS; + PRINTF( + "ERROR: Inside io_seproxyhal_display_icon, icon size (%d) is too big for the " + "buffer (%d-4)! (bitmap=0x%x, width=%d, height=%d, bpp=%d)\n", + length, + sizeof(G_io_seproxyhal_spi_buffer), + icon_details->bitmap, + icon_details->width, + icon_details->height, + icon_details->bpp); +#endif // defined(HAVE_PRINTF) + return; + } + G_io_seproxyhal_spi_buffer[0] = SEPROXYHAL_TAG_SCREEN_DISPLAY_STATUS; #if defined(HAVE_SE_SCREEN) && defined(HAVE_PRINTF) - G_io_seproxyhal_spi_buffer[0] = SEPROXYHAL_TAG_DBG_SCREEN_DISPLAY_STATUS; -#endif // HAVE_SE_SCREEN && HAVE_PRINTF - G_io_seproxyhal_spi_buffer[1] = length>>8; - G_io_seproxyhal_spi_buffer[2] = length; - io_seproxyhal_spi_send(G_io_seproxyhal_spi_buffer, 3); - io_seproxyhal_spi_send((const uint8_t *) icon_component, sizeof(bagl_component_t)); - G_io_seproxyhal_spi_buffer[0] = icon_details->bpp; - io_seproxyhal_spi_send(G_io_seproxyhal_spi_buffer, 1); - io_seproxyhal_spi_send((const uint8_t *) PIC(icon_details->colors), h); - io_seproxyhal_spi_send((const uint8_t *) PIC(icon_details->bitmap), w); -#else // !HAVE_SE_SCREEN || (HAVE_SE_SCREEN && HAVE_PRINTF) - (void) icon_component; -#endif // !HAVE_SE_SCREEN || (HAVE_SE_SCREEN && HAVE_PRINTF) -#endif // !SEPROXYHAL_TAG_SCREEN_DISPLAY_RAW_STATUS - } + G_io_seproxyhal_spi_buffer[0] = SEPROXYHAL_TAG_DBG_SCREEN_DISPLAY_STATUS; +#endif // HAVE_SE_SCREEN && HAVE_PRINTF + G_io_seproxyhal_spi_buffer[1] = length >> 8; + G_io_seproxyhal_spi_buffer[2] = length; + io_seproxyhal_spi_send(G_io_seproxyhal_spi_buffer, 3); + io_seproxyhal_spi_send((const uint8_t *) icon_component, sizeof(bagl_component_t)); + G_io_seproxyhal_spi_buffer[0] = icon_details->bpp; + io_seproxyhal_spi_send(G_io_seproxyhal_spi_buffer, 1); + io_seproxyhal_spi_send((const uint8_t *) PIC(icon_details->colors), h); + io_seproxyhal_spi_send((const uint8_t *) PIC(icon_details->bitmap), w); +#else // !HAVE_SE_SCREEN || (HAVE_SE_SCREEN && HAVE_PRINTF) + (void) icon_component; +#endif // !HAVE_SE_SCREEN || (HAVE_SE_SCREEN && HAVE_PRINTF) +#endif // !SEPROXYHAL_TAG_SCREEN_DISPLAY_RAW_STATUS + } } -void io_seproxyhal_display_default(const bagl_element_t* element) { - - const bagl_element_t* el = (const bagl_element_t*) PIC(element); - const char* txt; - // process automagically address from rom and from ram - unsigned int type = (el->component.type & ~(BAGL_FLAG_TOUCHABLE)); +void io_seproxyhal_display_default(const bagl_element_t *element) +{ + const bagl_element_t *el = (const bagl_element_t *) PIC(element); + const char *txt; + // process automagically address from rom and from ram + unsigned int type = (el->component.type & ~(BAGL_FLAG_TOUCHABLE)); #if defined(HAVE_INDEXED_STRINGS) - if (type == BAGL_LABELINE_LOC) { - txt = (const char*)PIC(get_ux_loc_string(el->index)); - } else -#endif //defined(HAVE_INDEXED_STRINGS) - { - txt = (const char*)PIC(el->text); - } - - if (type != BAGL_NONE) { - if (txt != NULL) { - // consider an icon details descriptor is pointed by the context - if (type == BAGL_ICON && el->component.icon_id == 0) { - // SECURITY: due to this wild cast, the code MUST be executed on the application side instead of in - // the syscall sides to avoid buffer overflows and a real hard way of checking buffer - // belonging in the syscall dispatch - io_seproxyhal_display_icon(&el->component, (const bagl_icon_details_t *) txt); - } - else { + if (type == BAGL_LABELINE_LOC) { + txt = (const char *) PIC(get_ux_loc_string(el->index)); + } + else +#endif // defined(HAVE_INDEXED_STRINGS) + { + txt = (const char *) PIC(el->text); + } + + if (type != BAGL_NONE) { + if (txt != NULL) { + // consider an icon details descriptor is pointed by the context + if (type == BAGL_ICON && el->component.icon_id == 0) { + // SECURITY: due to this wild cast, the code MUST be executed on the application + // side instead of in + // the syscall sides to avoid buffer overflows and a real hard way of + // checking buffer belonging in the syscall dispatch + io_seproxyhal_display_icon(&el->component, (const bagl_icon_details_t *) txt); + } + else { #ifdef HAVE_SE_SCREEN - bagl_draw_with_context(&el->component, txt, strlen(txt), BAGL_ENCODING_DEFAULT); -#endif // HAVE_SE_SCREEN + bagl_draw_with_context(&el->component, txt, strlen(txt), BAGL_ENCODING_DEFAULT); +#endif // HAVE_SE_SCREEN #if !defined(HAVE_SE_SCREEN) || (defined(HAVE_SE_SCREEN) && defined(HAVE_PRINTF)) - if (io_seproxyhal_spi_is_status_sent()) { - return; - } - // io_seph_send crash when using txt from language packs... - // ...let's use an intermediate buffer to store txt + if (io_seproxyhal_spi_is_status_sent()) { + return; + } + // io_seph_send crash when using txt from language packs... + // ...let's use an intermediate buffer to store txt #ifdef HAVE_LANGUAGE_PACK - char buffer[128]; - strlcpy(buffer, txt, sizeof(buffer)); -#else //HAVE_LANGUAGE_PACK - const char *buffer = txt; -#endif //HAVE_LANGUAGE_PACK - unsigned short length = sizeof(bagl_component_t)+strlen(buffer); - if (length > (sizeof(G_io_seproxyhal_spi_buffer)-3)) { + char buffer[128]; + strlcpy(buffer, txt, sizeof(buffer)); +#else // HAVE_LANGUAGE_PACK + const char *buffer = txt; +#endif // HAVE_LANGUAGE_PACK + unsigned short length = sizeof(bagl_component_t) + strlen(buffer); + if (length > (sizeof(G_io_seproxyhal_spi_buffer) - 3)) { #if defined(HAVE_PRINTF) - PRINTF("ERROR: Inside io_seproxyhal_display_default, length (%d) is too big for G_io_seproxyhal_spi_buffer(%d)!\n", length+3, sizeof(G_io_seproxyhal_spi_buffer)); -#endif //defined(HAVE_PRINTF) - return; - } - G_io_seproxyhal_spi_buffer[0] = SEPROXYHAL_TAG_SCREEN_DISPLAY_STATUS; + PRINTF( + "ERROR: Inside io_seproxyhal_display_default, length (%d) is too big for " + "G_io_seproxyhal_spi_buffer(%d)!\n", + length + 3, + sizeof(G_io_seproxyhal_spi_buffer)); +#endif // defined(HAVE_PRINTF) + return; + } + G_io_seproxyhal_spi_buffer[0] = SEPROXYHAL_TAG_SCREEN_DISPLAY_STATUS; #if defined(HAVE_SE_SCREEN) && defined(HAVE_PRINTF) - G_io_seproxyhal_spi_buffer[0] = SEPROXYHAL_TAG_DBG_SCREEN_DISPLAY_STATUS; -#endif // HAVE_SE_SCREEN && HAVE_PRINTF - G_io_seproxyhal_spi_buffer[1] = length>>8; - G_io_seproxyhal_spi_buffer[2] = length; - io_seproxyhal_spi_send(G_io_seproxyhal_spi_buffer, 3); - io_seproxyhal_spi_send((const uint8_t *)&el->component, sizeof(bagl_component_t)); - io_seproxyhal_spi_send((const uint8_t *)buffer, strlen(buffer)); -#endif // !HAVE_SE_SCREEN || (HAVE_SE_SCREEN && HAVE_PRINTF) - } - } - else { + G_io_seproxyhal_spi_buffer[0] = SEPROXYHAL_TAG_DBG_SCREEN_DISPLAY_STATUS; +#endif // HAVE_SE_SCREEN && HAVE_PRINTF + G_io_seproxyhal_spi_buffer[1] = length >> 8; + G_io_seproxyhal_spi_buffer[2] = length; + io_seproxyhal_spi_send(G_io_seproxyhal_spi_buffer, 3); + io_seproxyhal_spi_send((const uint8_t *) &el->component, sizeof(bagl_component_t)); + io_seproxyhal_spi_send((const uint8_t *) buffer, strlen(buffer)); +#endif // !HAVE_SE_SCREEN || (HAVE_SE_SCREEN && HAVE_PRINTF) + } + } + else { #ifdef HAVE_SE_SCREEN - bagl_draw_with_context(&el->component, NULL, 0, 0); -#endif // HAVE_SE_SCREEN + bagl_draw_with_context(&el->component, NULL, 0, 0); +#endif // HAVE_SE_SCREEN #if !defined(HAVE_SE_SCREEN) || (defined(HAVE_SE_SCREEN) && defined(HAVE_PRINTF)) - if (io_seproxyhal_spi_is_status_sent()) { - return; - } - unsigned short length = sizeof(bagl_component_t); - G_io_seproxyhal_spi_buffer[0] = SEPROXYHAL_TAG_SCREEN_DISPLAY_STATUS; + if (io_seproxyhal_spi_is_status_sent()) { + return; + } + unsigned short length = sizeof(bagl_component_t); + G_io_seproxyhal_spi_buffer[0] = SEPROXYHAL_TAG_SCREEN_DISPLAY_STATUS; #if defined(HAVE_SE_SCREEN) && defined(HAVE_PRINTF) - G_io_seproxyhal_spi_buffer[0] = SEPROXYHAL_TAG_DBG_SCREEN_DISPLAY_STATUS; -#endif // HAVE_SE_SCREEN && HAVE_PRINTF - G_io_seproxyhal_spi_buffer[1] = length>>8; - G_io_seproxyhal_spi_buffer[2] = length; - io_seproxyhal_spi_send(G_io_seproxyhal_spi_buffer, 3); - io_seproxyhal_spi_send((const uint8_t *) &el->component, sizeof(bagl_component_t)); -#endif // !HAVE_SE_SCREEN || (HAVE_SE_SCREEN && HAVE_PRINTF) + G_io_seproxyhal_spi_buffer[0] = SEPROXYHAL_TAG_DBG_SCREEN_DISPLAY_STATUS; +#endif // HAVE_SE_SCREEN && HAVE_PRINTF + G_io_seproxyhal_spi_buffer[1] = length >> 8; + G_io_seproxyhal_spi_buffer[2] = length; + io_seproxyhal_spi_send(G_io_seproxyhal_spi_buffer, 3); + io_seproxyhal_spi_send((const uint8_t *) &el->component, sizeof(bagl_component_t)); +#endif // !HAVE_SE_SCREEN || (HAVE_SE_SCREEN && HAVE_PRINTF) + } } - } } -unsigned int bagl_label_roundtrip_duration_ms(const bagl_element_t* e, unsigned int average_char_width) { - return bagl_label_roundtrip_duration_ms_buf(e, e->text, average_char_width); +unsigned int bagl_label_roundtrip_duration_ms(const bagl_element_t *e, + unsigned int average_char_width) +{ + return bagl_label_roundtrip_duration_ms_buf(e, e->text, average_char_width); } -unsigned int bagl_label_roundtrip_duration_ms_buf(const bagl_element_t* e, const char* str, unsigned int average_char_width) { - // not a scrollable label - if (e == NULL || (e->component.type != BAGL_LABEL && e->component.type != BAGL_LABELINE)) { - return 0; - } +unsigned int bagl_label_roundtrip_duration_ms_buf(const bagl_element_t *e, + const char *str, + unsigned int average_char_width) +{ + // not a scrollable label + if (e == NULL || (e->component.type != BAGL_LABEL && e->component.type != BAGL_LABELINE)) { + return 0; + } - const char *text_adr = (const char *) PIC(str); - unsigned int textlen = 0; + const char *text_adr = (const char *) PIC(str); + unsigned int textlen = 0; - // no delay, no text to display - if (!text_adr) { - return 0; - } - textlen = strlen(text_adr); + // no delay, no text to display + if (!text_adr) { + return 0; + } + textlen = strlen(text_adr); - // no delay, all text fits - textlen = textlen * average_char_width; - if (textlen <= e->component.width) { - return 0; - } + // no delay, all text fits + textlen = textlen * average_char_width; + if (textlen <= e->component.width) { + return 0; + } - // compute scrolled text length - return 2*(textlen - e->component.width)*1000/e->component.icon_id + 2*(e->component.stroke & ~(0x80))*100; + // compute scrolled text length + return 2 * (textlen - e->component.width) * 1000 / e->component.icon_id + + 2 * (e->component.stroke & ~(0x80)) * 100; } -void io_seproxyhal_button_push(button_push_callback_t button_callback, unsigned int new_button_mask) { - if (button_callback) { - unsigned int button_mask; - unsigned int button_same_mask_counter; - // enable speeded up long push - if (new_button_mask == G_ux_os.button_mask) { - // each 100ms ~ - G_ux_os.button_same_mask_counter++; - } +void io_seproxyhal_button_push(button_push_callback_t button_callback, unsigned int new_button_mask) +{ + if (button_callback) { + unsigned int button_mask; + unsigned int button_same_mask_counter; + // enable speeded up long push + if (new_button_mask == G_ux_os.button_mask) { + // each 100ms ~ + G_ux_os.button_same_mask_counter++; + } - // when new_button_mask is 0 and + // when new_button_mask is 0 and - // append the button mask - button_mask = G_ux_os.button_mask | new_button_mask; + // append the button mask + button_mask = G_ux_os.button_mask | new_button_mask; - // pre reset variable due to os_sched_exit - button_same_mask_counter = G_ux_os.button_same_mask_counter; + // pre reset variable due to os_sched_exit + button_same_mask_counter = G_ux_os.button_same_mask_counter; - // reset button mask - if (new_button_mask == 0) { - // reset next state when button are released - G_ux_os.button_mask = 0; - G_ux_os.button_same_mask_counter=0; + // reset button mask + if (new_button_mask == 0) { + // reset next state when button are released + G_ux_os.button_mask = 0; + G_ux_os.button_same_mask_counter = 0; - // notify button released event - button_mask |= BUTTON_EVT_RELEASED; - } - else { - G_ux_os.button_mask = button_mask; - } + // notify button released event + button_mask |= BUTTON_EVT_RELEASED; + } + else { + G_ux_os.button_mask = button_mask; + } - // reset counter when button mask changes - if (new_button_mask != G_ux_os.button_mask) { - G_ux_os.button_same_mask_counter=0; - } + // reset counter when button mask changes + if (new_button_mask != G_ux_os.button_mask) { + G_ux_os.button_same_mask_counter = 0; + } - if (button_same_mask_counter >= BUTTON_FAST_THRESHOLD_CS) { - // fast bit when pressing and timing is right - if ((button_same_mask_counter%BUTTON_FAST_ACTION_CS) == 0) { - button_mask |= BUTTON_EVT_FAST; - } - - /* - // fast bit when releasing and threshold has been exceeded - if ((button_mask & BUTTON_EVT_RELEASED)) { - button_mask |= BUTTON_EVT_FAST; - } - */ - - // discard the release event after a fastskip has been detected, to avoid strange at release behavior - // and also to enable user to cancel an operation by starting triggering the fast skip - button_mask &= ~BUTTON_EVT_RELEASED; - } + if (button_same_mask_counter >= BUTTON_FAST_THRESHOLD_CS) { + // fast bit when pressing and timing is right + if ((button_same_mask_counter % BUTTON_FAST_ACTION_CS) == 0) { + button_mask |= BUTTON_EVT_FAST; + } - // indicate if button have been released - button_callback(button_mask, button_same_mask_counter); + /* + // fast bit when releasing and threshold has been exceeded + if ((button_mask & BUTTON_EVT_RELEASED)) { + button_mask |= BUTTON_EVT_FAST; + } + */ + + // discard the release event after a fastskip has been detected, to avoid strange at + // release behavior and also to enable user to cancel an operation by starting + // triggering the fast skip + button_mask &= ~BUTTON_EVT_RELEASED; + } - } + // indicate if button have been released + button_callback(button_mask, button_same_mask_counter); + } } -#endif // HAVE_BAGL +#endif // HAVE_BAGL -void io_seproxyhal_setup_ticker(unsigned int interval_ms) { - uint8_t buffer[5]; - buffer[0] = SEPROXYHAL_TAG_SET_TICKER_INTERVAL; - buffer[1] = 0; - buffer[2] = 2; - buffer[3] = (interval_ms>>8)&0xff; - buffer[4] = (interval_ms)&0xff; - io_seproxyhal_spi_send(buffer, 5); +void io_seproxyhal_setup_ticker(unsigned int interval_ms) +{ + uint8_t buffer[5]; + buffer[0] = SEPROXYHAL_TAG_SET_TICKER_INTERVAL; + buffer[1] = 0; + buffer[2] = 2; + buffer[3] = (interval_ms >> 8) & 0xff; + buffer[4] = (interval_ms) &0xff; + io_seproxyhal_spi_send(buffer, 5); } -void io_seproxyhal_power_off(bool criticalBattery) { - unsigned char seph_io_device_off[4] = { - SEPROXYHAL_TAG_DEVICE_OFF, - 0, - 1, - (char) criticalBattery, - }; - io_seproxyhal_spi_send(seph_io_device_off, sizeof(seph_io_device_off)); - for(;;); +void io_seproxyhal_power_off(bool criticalBattery) +{ + unsigned char seph_io_device_off[4] = { + SEPROXYHAL_TAG_DEVICE_OFF, + 0, + 1, + (char) criticalBattery, + }; + io_seproxyhal_spi_send(seph_io_device_off, sizeof(seph_io_device_off)); + for (;;) + ; } -static const unsigned char seph_io_se_reset[]= { - SEPROXYHAL_TAG_SE_POWER_OFF, - 0, - 0, +static const unsigned char seph_io_se_reset[] = { + SEPROXYHAL_TAG_SE_POWER_OFF, + 0, + 0, }; -void io_seproxyhal_se_reset(void) { - io_seproxyhal_spi_send(seph_io_se_reset, sizeof(seph_io_se_reset)); - for(;;); +void io_seproxyhal_se_reset(void) +{ + io_seproxyhal_spi_send(seph_io_se_reset, sizeof(seph_io_se_reset)); + for (;;) + ; } #ifdef HAVE_SERIALIZED_NBGL @@ -956,583 +1026,616 @@ void io_seproxyhal_se_reset(void) { static uint8_t nbgl_serialize_buffer[SERIALIZED_NBGL_MAX_LEN]; -void io_seproxyhal_send_nbgl_serialized(nbgl_serialized_event_type_e event, nbgl_obj_t *obj) { - // Serialize object - size_t len = 0; - size_t max_len = sizeof(nbgl_serialize_buffer) - 3; - uint8_t status = nbgl_serializeNbglEvent(event, obj, nbgl_serialize_buffer + 3, &len, max_len); - - // Encode and send - if (status == NBGL_SERIALIZE_OK) { - nbgl_serialize_buffer[0] = SEPROXYHAL_TAG_NBGL_SERIALIZED; - U2BE_ENCODE(nbgl_serialize_buffer, 1, len); - io_seproxyhal_spi_send(nbgl_serialize_buffer, len + 3); - } +void io_seproxyhal_send_nbgl_serialized(nbgl_serialized_event_type_e event, nbgl_obj_t *obj) +{ + // Serialize object + size_t len = 0; + size_t max_len = sizeof(nbgl_serialize_buffer) - 3; + uint8_t status = nbgl_serializeNbglEvent(event, obj, nbgl_serialize_buffer + 3, &len, max_len); + + // Encode and send + if (status == NBGL_SERIALIZE_OK) { + nbgl_serialize_buffer[0] = SEPROXYHAL_TAG_NBGL_SERIALIZED; + U2BE_ENCODE(nbgl_serialize_buffer, 1, len); + io_seproxyhal_spi_send(nbgl_serialize_buffer, len + 3); + } } #endif #ifdef HAVE_BLE void io_seph_ble_enable(unsigned char enable) { - G_io_seproxyhal_spi_buffer[0] = SEPROXYHAL_TAG_UX_CMD; - G_io_seproxyhal_spi_buffer[1] = 0; - G_io_seproxyhal_spi_buffer[2] = 1; - G_io_seproxyhal_spi_buffer[3] = (enable ? SEPROXYHAL_TAG_UX_CMD_BLE_ENABLE_ADV : SEPROXYHAL_TAG_UX_CMD_BLE_DISABLE_ADV); - io_seproxyhal_spi_send(G_io_seproxyhal_spi_buffer, 4); + G_io_seproxyhal_spi_buffer[0] = SEPROXYHAL_TAG_UX_CMD; + G_io_seproxyhal_spi_buffer[1] = 0; + G_io_seproxyhal_spi_buffer[2] = 1; + G_io_seproxyhal_spi_buffer[3] + = (enable ? SEPROXYHAL_TAG_UX_CMD_BLE_ENABLE_ADV : SEPROXYHAL_TAG_UX_CMD_BLE_DISABLE_ADV); + io_seproxyhal_spi_send(G_io_seproxyhal_spi_buffer, 4); } void io_seph_ble_clear_bond_db(void) { - G_io_seproxyhal_spi_buffer[0] = SEPROXYHAL_TAG_UX_CMD; - G_io_seproxyhal_spi_buffer[1] = 0; - G_io_seproxyhal_spi_buffer[2] = 1; - G_io_seproxyhal_spi_buffer[3] = SEPROXYHAL_TAG_UX_CMD_BLE_RESET_PAIRINGS; - io_seproxyhal_spi_send(G_io_seproxyhal_spi_buffer, 4); + G_io_seproxyhal_spi_buffer[0] = SEPROXYHAL_TAG_UX_CMD; + G_io_seproxyhal_spi_buffer[1] = 0; + G_io_seproxyhal_spi_buffer[2] = 1; + G_io_seproxyhal_spi_buffer[3] = SEPROXYHAL_TAG_UX_CMD_BLE_RESET_PAIRINGS; + io_seproxyhal_spi_send(G_io_seproxyhal_spi_buffer, 4); } void io_seph_ble_name_changed(void) { - G_io_seproxyhal_spi_buffer[0] = SEPROXYHAL_TAG_UX_CMD; - G_io_seproxyhal_spi_buffer[1] = 0; - G_io_seproxyhal_spi_buffer[2] = 1; - G_io_seproxyhal_spi_buffer[3] = SEPROXYHAL_TAG_UX_CMD_BLE_NAME_CHANGED; - io_seproxyhal_spi_send(G_io_seproxyhal_spi_buffer, 4); + G_io_seproxyhal_spi_buffer[0] = SEPROXYHAL_TAG_UX_CMD; + G_io_seproxyhal_spi_buffer[1] = 0; + G_io_seproxyhal_spi_buffer[2] = 1; + G_io_seproxyhal_spi_buffer[3] = SEPROXYHAL_TAG_UX_CMD_BLE_NAME_CHANGED; + io_seproxyhal_spi_send(G_io_seproxyhal_spi_buffer, 4); } -#endif // HAVE_BLE +#endif // HAVE_BLE void io_seph_ux_redisplay(void) { - G_io_seproxyhal_spi_buffer[0] = SEPROXYHAL_TAG_UX_CMD; - G_io_seproxyhal_spi_buffer[1] = 0; - G_io_seproxyhal_spi_buffer[2] = 1; - G_io_seproxyhal_spi_buffer[3] = SEPROXYHAL_TAG_UX_CMD_REDISPLAY; - io_seproxyhal_spi_send(G_io_seproxyhal_spi_buffer, 4); + G_io_seproxyhal_spi_buffer[0] = SEPROXYHAL_TAG_UX_CMD; + G_io_seproxyhal_spi_buffer[1] = 0; + G_io_seproxyhal_spi_buffer[2] = 1; + G_io_seproxyhal_spi_buffer[3] = SEPROXYHAL_TAG_UX_CMD_REDISPLAY; + io_seproxyhal_spi_send(G_io_seproxyhal_spi_buffer, 4); } static const unsigned char seph_io_usb_disconnect[] = { - SEPROXYHAL_TAG_USB_CONFIG, - 0, - 1, - SEPROXYHAL_TAG_USB_CONFIG_DISCONNECT, + SEPROXYHAL_TAG_USB_CONFIG, + 0, + 1, + SEPROXYHAL_TAG_USB_CONFIG_DISCONNECT, }; -void io_seproxyhal_disable_io(void) { +void io_seproxyhal_disable_io(void) +{ // usb off io_seproxyhal_spi_send(seph_io_usb_disconnect, sizeof(seph_io_usb_disconnect)); } -void io_seproxyhal_backlight(unsigned int flags, unsigned int backlight_percentage) { - G_io_seproxyhal_spi_buffer[0] = SEPROXYHAL_TAG_SET_SCREEN_CONFIG; - G_io_seproxyhal_spi_buffer[1] = 0; - G_io_seproxyhal_spi_buffer[2] = 2; - G_io_seproxyhal_spi_buffer[3] = (backlight_percentage?0x80:0)|(flags & 0x7F); // power on - G_io_seproxyhal_spi_buffer[4] = backlight_percentage; - io_seproxyhal_spi_send(G_io_seproxyhal_spi_buffer, 5); +void io_seproxyhal_backlight(unsigned int flags, unsigned int backlight_percentage) +{ + G_io_seproxyhal_spi_buffer[0] = SEPROXYHAL_TAG_SET_SCREEN_CONFIG; + G_io_seproxyhal_spi_buffer[1] = 0; + G_io_seproxyhal_spi_buffer[2] = 2; + G_io_seproxyhal_spi_buffer[3] = (backlight_percentage ? 0x80 : 0) | (flags & 0x7F); // power on + G_io_seproxyhal_spi_buffer[4] = backlight_percentage; + io_seproxyhal_spi_send(G_io_seproxyhal_spi_buffer, 5); } - #ifdef HAVE_IO_U2F u2f_service_t G_io_u2f; -#endif // HAVE_IO_U2F +#endif // HAVE_IO_U2F unsigned int os_io_seproxyhal_get_app_name_and_version(void) __attribute__((weak)); -unsigned int os_io_seproxyhal_get_app_name_and_version(void) { - unsigned int tx_len, len; - // build the get app name and version reply - tx_len = 0; - G_io_apdu_buffer[tx_len++] = 1; // format ID +unsigned int os_io_seproxyhal_get_app_name_and_version(void) +{ + unsigned int tx_len, len; + // build the get app name and version reply + tx_len = 0; + G_io_apdu_buffer[tx_len++] = 1; // format ID #ifndef HAVE_BOLOS - // append app name - len = os_registry_get_current_app_tag(BOLOS_TAG_APPNAME, G_io_apdu_buffer+tx_len+1, sizeof(G_io_apdu_buffer)-tx_len-1); - G_io_apdu_buffer[tx_len++] = len; - tx_len += len; - // append app version - len = os_registry_get_current_app_tag(BOLOS_TAG_APPVERSION, G_io_apdu_buffer+tx_len+1, sizeof(G_io_apdu_buffer)-tx_len-1); - G_io_apdu_buffer[tx_len++] = len; - tx_len += len; -#else // HAVE_BOLOS - // append app name - len = strlen("BOLOS"); - G_io_apdu_buffer[tx_len++] = len; - strcpy((char*)(G_io_apdu_buffer+tx_len), "BOLOS"); - tx_len += len; - // append app version - len = strlen(VERSION); - G_io_apdu_buffer[tx_len++] = len; - strcpy((char*)(G_io_apdu_buffer+tx_len), VERSION); - tx_len += len; -#endif // HAVE_BOLOS + // append app name + len = os_registry_get_current_app_tag( + BOLOS_TAG_APPNAME, G_io_apdu_buffer + tx_len + 1, sizeof(G_io_apdu_buffer) - tx_len - 1); + G_io_apdu_buffer[tx_len++] = len; + tx_len += len; + // append app version + len = os_registry_get_current_app_tag( + BOLOS_TAG_APPVERSION, G_io_apdu_buffer + tx_len + 1, sizeof(G_io_apdu_buffer) - tx_len - 1); + G_io_apdu_buffer[tx_len++] = len; + tx_len += len; +#else // HAVE_BOLOS + // append app name + len = strlen("BOLOS"); + G_io_apdu_buffer[tx_len++] = len; + strcpy((char *) (G_io_apdu_buffer + tx_len), "BOLOS"); + tx_len += len; + // append app version + len = strlen(VERSION); + G_io_apdu_buffer[tx_len++] = len; + strcpy((char *) (G_io_apdu_buffer + tx_len), VERSION); + tx_len += len; +#endif // HAVE_BOLOS #if !defined(HAVE_IO_TASK) || !defined(HAVE_BOLOS) - // to be fixed within io tasks - // return OS flags to notify of platform's global state (pin lock etc) - G_io_apdu_buffer[tx_len++] = 1; // flags length - G_io_apdu_buffer[tx_len++] = os_flags(); -#endif // !defined(HAVE_IO_TASK) || !defined(HAVE_BOLOS) - - // status words - G_io_apdu_buffer[tx_len++] = 0x90; - G_io_apdu_buffer[tx_len++] = 0x00; - return tx_len; + // to be fixed within io tasks + // return OS flags to notify of platform's global state (pin lock etc) + G_io_apdu_buffer[tx_len++] = 1; // flags length + G_io_apdu_buffer[tx_len++] = os_flags(); +#endif // !defined(HAVE_IO_TASK) || !defined(HAVE_BOLOS) + + // status words + G_io_apdu_buffer[tx_len++] = 0x90; + G_io_apdu_buffer[tx_len++] = 0x00; + return tx_len; } #if !defined(HAVE_BOLOS_NO_DEFAULT_APDU) // This function is used to process the default APDU commands. -static bolos_bool_t io_process_default_apdus(unsigned char* channel, unsigned short* tx_len) { - // Indicates whether a command has been processed and need to send an answer. - bolos_bool_t processed = BOLOS_FALSE; - - // We handle the default apdus when the CLA byte is correct. - if (DEFAULT_APDU_CLA == G_io_apdu_buffer[APDU_OFF_CLA]) { - - // We have several possible commands. - switch (G_io_apdu_buffer[APDU_OFF_INS]) { - - // get name and version - case DEFAULT_APDU_INS_GET_VERSION: - // P1 and P2 shall be set to '00'. - if (!G_io_apdu_buffer[APDU_OFF_P1] && !G_io_apdu_buffer[APDU_OFF_P2]) { - *tx_len = os_io_seproxyhal_get_app_name_and_version(); - // disable 'return after tx' and 'asynch reply' flags - *channel &= ~IO_FLAGS; - processed = BOLOS_TRUE; - } - break; - - // exit app after replied - case DEFAULT_APDU_INS_APP_EXIT: - // P1 and P2 shall be set to '00'. - if (!G_io_apdu_buffer[APDU_OFF_P1] && !G_io_apdu_buffer[APDU_OFF_P2]) { - *tx_len = 0; - G_io_apdu_buffer[(*tx_len)++] = 0x90; - G_io_apdu_buffer[(*tx_len)++] = 0x00; - // disable 'return after tx' and 'asynch reply' flags - *channel &= ~IO_FLAGS; - // If this APDU has been received from the dashboard, we don't do - // anything except resetting the IO flags. +static bolos_bool_t io_process_default_apdus(unsigned char *channel, unsigned short *tx_len) +{ + // Indicates whether a command has been processed and need to send an answer. + bolos_bool_t processed = BOLOS_FALSE; + + // We handle the default apdus when the CLA byte is correct. + if (DEFAULT_APDU_CLA == G_io_apdu_buffer[APDU_OFF_CLA]) { + // We have several possible commands. + switch (G_io_apdu_buffer[APDU_OFF_INS]) { + // get name and version + case DEFAULT_APDU_INS_GET_VERSION: + // P1 and P2 shall be set to '00'. + if (!G_io_apdu_buffer[APDU_OFF_P1] && !G_io_apdu_buffer[APDU_OFF_P2]) { + *tx_len = os_io_seproxyhal_get_app_name_and_version(); + // disable 'return after tx' and 'asynch reply' flags + *channel &= ~IO_FLAGS; + processed = BOLOS_TRUE; + } + break; + + // exit app after replied + case DEFAULT_APDU_INS_APP_EXIT: + // P1 and P2 shall be set to '00'. + if (!G_io_apdu_buffer[APDU_OFF_P1] && !G_io_apdu_buffer[APDU_OFF_P2]) { + *tx_len = 0; + G_io_apdu_buffer[(*tx_len)++] = 0x90; + G_io_apdu_buffer[(*tx_len)++] = 0x00; + // disable 'return after tx' and 'asynch reply' flags + *channel &= ~IO_FLAGS; + // If this APDU has been received from the dashboard, we don't do + // anything except resetting the IO flags. #if !defined(HAVE_BOLOS) - // We exit the application after having replied. - *channel |= IO_RESET_AFTER_REPLIED; + // We exit the application after having replied. + *channel |= IO_RESET_AFTER_REPLIED; #endif - processed = BOLOS_TRUE; - } - break; + processed = BOLOS_TRUE; + } + break; - // seed cookie - // host: - // device: 9000 | 6985 + // seed cookie + // host: + // device: 9000 | + // 6985 #if defined(HAVE_SEED_COOKIE) - case DEFAULT_APDU_INS_GET_SEED_COOKIE: - // P1 and P2 shall be set to '00'. - if (!G_io_apdu_buffer[APDU_OFF_P1] && !G_io_apdu_buffer[APDU_OFF_P2]) { - *tx_len = 0; - if (os_global_pin_is_validated() == BOLOS_UX_OK) { - // format - G_io_apdu_buffer[(*tx_len)++] = 0x01; - - _Static_assert(sizeof(G_io_apdu_buffer)-1-1-2 >= CX_SHA512_SIZE, - "structure size required 64 bytes"); - bolos_bool_t seed_generated = os_perso_seed_cookie(G_io_apdu_buffer+1+1); - if (seed_generated == BOLOS_TRUE) { - G_io_apdu_buffer[(*tx_len)++] = CX_SHA512_SIZE; - *tx_len += CX_SHA512_SIZE; - } else { - G_io_apdu_buffer[(*tx_len)++] = 0; - } - - G_io_apdu_buffer[(*tx_len)++] = 0x90; - G_io_apdu_buffer[(*tx_len)++] = 0x00; - } - else { - G_io_apdu_buffer[(*tx_len)++] = 0x69; - G_io_apdu_buffer[(*tx_len)++] = 0x85; - } - *channel &= ~IO_FLAGS; - processed = BOLOS_TRUE; - } - break; -#endif // HAVE_SEED_COOKIE + case DEFAULT_APDU_INS_GET_SEED_COOKIE: + // P1 and P2 shall be set to '00'. + if (!G_io_apdu_buffer[APDU_OFF_P1] && !G_io_apdu_buffer[APDU_OFF_P2]) { + *tx_len = 0; + if (os_global_pin_is_validated() == BOLOS_UX_OK) { + // format + G_io_apdu_buffer[(*tx_len)++] = 0x01; + + _Static_assert(sizeof(G_io_apdu_buffer) - 1 - 1 - 2 >= CX_SHA512_SIZE, + "structure size required 64 bytes"); + bolos_bool_t seed_generated + = os_perso_seed_cookie(G_io_apdu_buffer + 1 + 1); + if (seed_generated == BOLOS_TRUE) { + G_io_apdu_buffer[(*tx_len)++] = CX_SHA512_SIZE; + *tx_len += CX_SHA512_SIZE; + } + else { + G_io_apdu_buffer[(*tx_len)++] = 0; + } + + G_io_apdu_buffer[(*tx_len)++] = 0x90; + G_io_apdu_buffer[(*tx_len)++] = 0x00; + } + else { + G_io_apdu_buffer[(*tx_len)++] = 0x69; + G_io_apdu_buffer[(*tx_len)++] = 0x85; + } + *channel &= ~IO_FLAGS; + processed = BOLOS_TRUE; + } + break; +#endif // HAVE_SEED_COOKIE #if defined(DEBUG_OS_STACK_CONSUMPTION) - // OS stack consumption. - case DEFAULT_APDU_INS_STACK_CONSUMPTION: - // Initialization. - *tx_len = 2; - U2BE_ENCODE(G_io_apdu_buffer, 0x00, SWO_APD_HDR_0D); - - // P2 and Lc shall be set to '00'. - if (!G_io_apdu_buffer[APDU_OFF_P2] && !G_io_apdu_buffer[APDU_OFF_LC]) { - int s = os_stack_operations(G_io_apdu_buffer[APDU_OFF_P1]); - if (-1 != s) { - u4be_encode(G_io_apdu_buffer, 0x00, s); - *tx_len = sizeof(int); - G_io_apdu_buffer[(*tx_len)++] = 0x90; - G_io_apdu_buffer[(*tx_len)++] = 0x00; - } + // OS stack consumption. + case DEFAULT_APDU_INS_STACK_CONSUMPTION: + // Initialization. + *tx_len = 2; + U2BE_ENCODE(G_io_apdu_buffer, 0x00, SWO_APD_HDR_0D); + + // P2 and Lc shall be set to '00'. + if (!G_io_apdu_buffer[APDU_OFF_P2] && !G_io_apdu_buffer[APDU_OFF_LC]) { + int s = os_stack_operations(G_io_apdu_buffer[APDU_OFF_P1]); + if (-1 != s) { + u4be_encode(G_io_apdu_buffer, 0x00, s); + *tx_len = sizeof(int); + G_io_apdu_buffer[(*tx_len)++] = 0x90; + G_io_apdu_buffer[(*tx_len)++] = 0x00; + } + } + *channel &= ~IO_FLAGS; + processed = BOLOS_TRUE; + break; +#endif // DEBUG_OS_STACK_CONSUMPTION + + default: + // 'processed' is already initialized. + break; } - *channel &= ~IO_FLAGS; - processed = BOLOS_TRUE; - break; -#endif // DEBUG_OS_STACK_CONSUMPTION - - default: - // 'processed' is already initialized. - break; } - } - return processed; + return processed; } -#endif // HAVE_BOLOS_NO_DEFAULT_APDU +#endif // HAVE_BOLOS_NO_DEFAULT_APDU -unsigned short io_exchange(unsigned char channel, unsigned short tx_len) { - unsigned short rx_len; - unsigned int timeout_ms; +unsigned short io_exchange(unsigned char channel, unsigned short tx_len) +{ + unsigned short rx_len; + unsigned int timeout_ms; #ifdef HAVE_BOLOS_APP_STACK_CANARY - // behavior upon detected stack overflow is to reset the SE - if (app_stack_canary != APP_STACK_CANARY_MAGIC) { - io_seproxyhal_se_reset(); - } -#endif // HAVE_BOLOS_APP_STACK_CANARY + // behavior upon detected stack overflow is to reset the SE + if (app_stack_canary != APP_STACK_CANARY_MAGIC) { + io_seproxyhal_se_reset(); + } +#endif // HAVE_BOLOS_APP_STACK_CANARY #ifdef DEBUG_APDU - if ((channel&~(IO_FLAGS)) == CHANNEL_APDU) { - // ignore tx len + if ((channel & ~(IO_FLAGS)) == CHANNEL_APDU) { + // ignore tx len - // already received the data of the apdu when received the whole apdu - if ((channel & (CHANNEL_APDU|IO_RECEIVE_DATA)) == (CHANNEL_APDU|IO_RECEIVE_DATA)) { - // return apdu data - header - return G_io_apdu_length-5; - } + // already received the data of the apdu when received the whole apdu + if ((channel & (CHANNEL_APDU | IO_RECEIVE_DATA)) == (CHANNEL_APDU | IO_RECEIVE_DATA)) { + // return apdu data - header + return G_io_apdu_length - 5; + } - // fetch next apdu - if (debug_apdus_offset < sizeof(debug_apdus)) { - G_io_apdu_length = debug_apdus[debug_apdus_offset]&0xFF; - memcpy(G_io_apdu_buffer, &debug_apdus[debug_apdus_offset+1], G_io_apdu_length); - debug_apdus_offset += G_io_apdu_length+1; - return G_io_apdu_length; + // fetch next apdu + if (debug_apdus_offset < sizeof(debug_apdus)) { + G_io_apdu_length = debug_apdus[debug_apdus_offset] & 0xFF; + memcpy(G_io_apdu_buffer, &debug_apdus[debug_apdus_offset + 1], G_io_apdu_length); + debug_apdus_offset += G_io_apdu_length + 1; + return G_io_apdu_length; + } } - } -#endif // DEBUG_APDU +#endif // DEBUG_APDU reply_apdu: - switch(channel&~(IO_FLAGS)) { - case CHANNEL_APDU: - // TODO work up the spi state machine over the HAL proxy until an APDU is available + switch (channel & ~(IO_FLAGS)) { + case CHANNEL_APDU: + // TODO work up the spi state machine over the HAL proxy until an APDU is available + + if (tx_len && !(channel & IO_ASYNCH_REPLY)) { + // ensure it's our turn to send a command/status, could lag a bit before sending the + // reply + while (io_seproxyhal_spi_is_status_sent()) { + io_seproxyhal_spi_recv( + G_io_seproxyhal_spi_buffer, sizeof(G_io_seproxyhal_spi_buffer), 0); + // process without sending status on tickers etc, to ensure keeping the hand + os_io_seph_recv_and_process(1); + } - if (tx_len && !(channel&IO_ASYNCH_REPLY)) { - // ensure it's our turn to send a command/status, could lag a bit before sending the reply - while (io_seproxyhal_spi_is_status_sent()) { - io_seproxyhal_spi_recv(G_io_seproxyhal_spi_buffer, sizeof(G_io_seproxyhal_spi_buffer), 0); - // process without sending status on tickers etc, to ensure keeping the hand - os_io_seph_recv_and_process(1); - } - - // reinit sending timeout for APDU replied within io_exchange - timeout_ms = G_io_app.ms + IO_RAPDU_TRANSMIT_TIMEOUT_MS; - - // until the whole RAPDU is transmitted, send chunks using the current mode for communication - for (;;) { - switch(G_io_app.apdu_state) { - default: - // delegate to the hal in case of not generic transport mode (or asynch) - if (io_exchange_al(channel, tx_len) == 0) { - goto break_send; - } - FALL_THROUGH; - case APDU_IDLE: - LOG("invalid state for APDU reply\n"); - THROW(INVALID_STATE); - break; + // reinit sending timeout for APDU replied within io_exchange + timeout_ms = G_io_app.ms + IO_RAPDU_TRANSMIT_TIMEOUT_MS; + + // until the whole RAPDU is transmitted, send chunks using the current mode for + // communication + for (;;) { + switch (G_io_app.apdu_state) { + default: + // delegate to the hal in case of not generic transport mode (or asynch) + if (io_exchange_al(channel, tx_len) == 0) { + goto break_send; + } + FALL_THROUGH; + case APDU_IDLE: + LOG("invalid state for APDU reply\n"); + THROW(INVALID_STATE); + break; #ifdef HAVE_NFC - case APDU_NFC: - if (tx_len > sizeof(G_io_apdu_buffer)) { - THROW(INVALID_PARAMETER); - } - // reply the NFC APDU over SEPROXYHAL protocol - G_io_seproxyhal_spi_buffer[0] = SEPROXYHAL_TAG_NFC_RAPDU; - G_io_seproxyhal_spi_buffer[1] = (tx_len)>>8; - G_io_seproxyhal_spi_buffer[2] = (tx_len); - io_seproxyhal_spi_send(G_io_seproxyhal_spi_buffer, 3); - io_seproxyhal_spi_send(G_io_apdu_buffer, tx_len); - - // isngle packet reply, mark immediate idle - G_io_app.apdu_state = APDU_IDLE; - G_io_app.apdu_media = IO_APDU_MEDIA_NONE; - goto break_send; + case APDU_NFC: + if (tx_len > sizeof(G_io_apdu_buffer)) { + THROW(INVALID_PARAMETER); + } + // reply the NFC APDU over SEPROXYHAL protocol + G_io_seproxyhal_spi_buffer[0] = SEPROXYHAL_TAG_NFC_RAPDU; + G_io_seproxyhal_spi_buffer[1] = (tx_len) >> 8; + G_io_seproxyhal_spi_buffer[2] = (tx_len); + io_seproxyhal_spi_send(G_io_seproxyhal_spi_buffer, 3); + io_seproxyhal_spi_send(G_io_apdu_buffer, tx_len); + + // isngle packet reply, mark immediate idle + G_io_app.apdu_state = APDU_IDLE; + G_io_app.apdu_media = IO_APDU_MEDIA_NONE; + goto break_send; #endif - case APDU_RAW: - if (tx_len > sizeof(G_io_apdu_buffer)) { - THROW(INVALID_PARAMETER); - } - // reply the RAW APDU over SEPROXYHAL protocol - G_io_seproxyhal_spi_buffer[0] = SEPROXYHAL_TAG_RAPDU; - G_io_seproxyhal_spi_buffer[1] = (tx_len)>>8; - G_io_seproxyhal_spi_buffer[2] = (tx_len); - io_seproxyhal_spi_send(G_io_seproxyhal_spi_buffer, 3); - io_seproxyhal_spi_send(G_io_apdu_buffer, tx_len); - - // isngle packet reply, mark immediate idle - G_io_app.apdu_state = APDU_IDLE; - // finished, no chunking - goto break_send; + case APDU_RAW: + if (tx_len > sizeof(G_io_apdu_buffer)) { + THROW(INVALID_PARAMETER); + } + // reply the RAW APDU over SEPROXYHAL protocol + G_io_seproxyhal_spi_buffer[0] = SEPROXYHAL_TAG_RAPDU; + G_io_seproxyhal_spi_buffer[1] = (tx_len) >> 8; + G_io_seproxyhal_spi_buffer[2] = (tx_len); + io_seproxyhal_spi_send(G_io_seproxyhal_spi_buffer, 3); + io_seproxyhal_spi_send(G_io_apdu_buffer, tx_len); + + // isngle packet reply, mark immediate idle + G_io_app.apdu_state = APDU_IDLE; + // finished, no chunking + goto break_send; #ifdef HAVE_USB_APDU - case APDU_USB_HID: - // only send, don't perform synchronous reception of the next command (will be done later by the seproxyhal packet processing) - io_usb_hid_send(io_usb_send_apdu_data, tx_len, G_io_apdu_buffer); - goto break_send; + case APDU_USB_HID: + // only send, don't perform synchronous reception of the next command + // (will be done later by the seproxyhal packet processing) + io_usb_hid_send(io_usb_send_apdu_data, tx_len, G_io_apdu_buffer); + goto break_send; #ifdef HAVE_USB_CLASS_CCID - case APDU_USB_CCID: - io_usb_ccid_reply(G_io_apdu_buffer, tx_len); - goto break_send; -#endif // HAVE_USB_CLASS_CCID + case APDU_USB_CCID: + io_usb_ccid_reply(G_io_apdu_buffer, tx_len); + goto break_send; +#endif // HAVE_USB_CLASS_CCID #ifdef HAVE_WEBUSB - case APDU_USB_WEBUSB: - io_usb_hid_send(io_usb_send_apdu_data_ep0x83, tx_len, G_io_apdu_buffer); - goto break_send; -#endif // HAVE_WEBUSB -#endif // HAVE_USB_APDU - -#ifdef HAVE_BLE_APDU // versus U2F BLE - case APDU_BLE: - LEDGER_BLE_send(G_io_apdu_buffer, tx_len); - goto break_send; -#endif // HAVE_BLE_APDU - + case APDU_USB_WEBUSB: + io_usb_hid_send(io_usb_send_apdu_data_ep0x83, tx_len, G_io_apdu_buffer); + goto break_send; +#endif // HAVE_WEBUSB +#endif // HAVE_USB_APDU + +#ifdef HAVE_BLE_APDU // versus U2F BLE + case APDU_BLE: + LEDGER_BLE_send(G_io_apdu_buffer, tx_len); + goto break_send; +#endif // HAVE_BLE_APDU #ifdef HAVE_IO_U2F - // case to handle U2F channels. u2f apdu to be dispatched in the upper layers - case APDU_U2F: - // prepare reply, the remaining segments will be pumped during USB/BLE events handling while waiting for the next APDU - - // the reply has been prepared by the application, stop sending anti timeouts - u2f_message_set_autoreply_wait_user_presence(&G_io_u2f, false); - - // continue processing currently received command until completely received. - while(!u2f_message_repliable(&G_io_u2f)) { - - io_seproxyhal_general_status(); - do { - io_seproxyhal_spi_recv(G_io_seproxyhal_spi_buffer, sizeof(G_io_seproxyhal_spi_buffer), 0); - // check for reply timeout - if (G_io_app.ms >= timeout_ms) { - THROW(EXCEPTION_IO_RESET); - } - // avoid a general status to be replied - io_seproxyhal_handle_event(); - } while (io_seproxyhal_spi_is_status_sent()); - } + // case to handle U2F channels. u2f apdu to be dispatched in the upper + // layers + case APDU_U2F: + // prepare reply, the remaining segments will be pumped during USB/BLE + // events handling while waiting for the next APDU + + // the reply has been prepared by the application, stop sending anti + // timeouts + u2f_message_set_autoreply_wait_user_presence(&G_io_u2f, false); + + // continue processing currently received command until completely + // received. + while (!u2f_message_repliable(&G_io_u2f)) { + io_seproxyhal_general_status(); + do { + io_seproxyhal_spi_recv(G_io_seproxyhal_spi_buffer, + sizeof(G_io_seproxyhal_spi_buffer), + 0); + // check for reply timeout + if (G_io_app.ms >= timeout_ms) { + THROW(EXCEPTION_IO_RESET); + } + // avoid a general status to be replied + io_seproxyhal_handle_event(); + } while (io_seproxyhal_spi_is_status_sent()); + } #ifdef U2F_PROXY_MAGIC - // user presence + counter + rapdu + sw must fit the apdu buffer - if (1U+ 4U+ tx_len +2U > sizeof(G_io_apdu_buffer)) { - THROW(INVALID_PARAMETER); - } + // user presence + counter + rapdu + sw must fit the apdu buffer + if (1U + 4U + tx_len + 2U > sizeof(G_io_apdu_buffer)) { + THROW(INVALID_PARAMETER); + } + + // u2F tunnel needs the status words to be included in the signature + // response BLOB, do it now. always return 9000 in the signature to + // avoid error @ transport level in u2f layers. + G_io_apdu_buffer[tx_len] = 0x90; // G_io_apdu_buffer[tx_len-2]; + G_io_apdu_buffer[tx_len + 1] = 0x00; // G_io_apdu_buffer[tx_len-1]; + tx_len += 2; + memmove(G_io_apdu_buffer + APDU_OFF_DATA, G_io_apdu_buffer, tx_len); + // zeroize user presence and counter + memset(G_io_apdu_buffer, 0, APDU_OFF_DATA); + u2f_message_reply(&G_io_u2f, U2F_CMD_MSG, G_io_apdu_buffer, tx_len + 5); + +#else // U2F_PROXY_MAGIC + u2f_message_reply(&G_io_u2f, U2F_CMD_MSG, G_io_apdu_buffer, tx_len); +#endif // U2F_PROXY_MAGIC + goto break_send; +#endif // HAVE_IO_U2F + } + continue; + + break_send: + + // wait end of reply transmission + // TODO: add timeout here to avoid spending too much time when host has + // disconnected + while (G_io_app.apdu_state != APDU_IDLE) { + io_seproxyhal_general_status(); + do { + io_seproxyhal_spi_recv( + G_io_seproxyhal_spi_buffer, sizeof(G_io_seproxyhal_spi_buffer), 0); + // check for reply timeout (when asynch reply (over hid or u2f for + // example)) this case shall be covered by usb_ep_timeout but is not, + // investigate that + if (G_io_app.ms >= timeout_ms) { + THROW(EXCEPTION_IO_RESET); + } + // avoid a general status to be replied + io_seproxyhal_handle_event(); + } while (io_seproxyhal_spi_is_status_sent()); + } + // reset apdu state + G_io_app.apdu_state = APDU_IDLE; + G_io_app.apdu_media = IO_APDU_MEDIA_NONE; + + G_io_app.apdu_length = 0; + + // continue sending commands, don't issue status yet + if (channel & IO_RETURN_AFTER_TX) { + return 0; + } + // acknowledge the write request (general status OK) and no more command to + // follow (wait until another APDU container is received to continue unwrapping) + io_seproxyhal_general_status(); + break; + } - // u2F tunnel needs the status words to be included in the signature response BLOB, do it now. - // always return 9000 in the signature to avoid error @ transport level in u2f layers. - G_io_apdu_buffer[tx_len] = 0x90; //G_io_apdu_buffer[tx_len-2]; - G_io_apdu_buffer[tx_len+1] = 0x00; //G_io_apdu_buffer[tx_len-1]; - tx_len += 2; - memmove(G_io_apdu_buffer + APDU_OFF_DATA, G_io_apdu_buffer, tx_len); - // zeroize user presence and counter - memset(G_io_apdu_buffer, 0, APDU_OFF_DATA); - u2f_message_reply(&G_io_u2f, U2F_CMD_MSG, G_io_apdu_buffer, tx_len+5); - -#else // U2F_PROXY_MAGIC - u2f_message_reply(&G_io_u2f, U2F_CMD_MSG, G_io_apdu_buffer, tx_len); -#endif // U2F_PROXY_MAGIC - goto break_send; -#endif // HAVE_IO_U2F - } - continue; - - break_send: - - // wait end of reply transmission - // TODO: add timeout here to avoid spending too much time when host has disconnected - while (G_io_app.apdu_state != APDU_IDLE) { - io_seproxyhal_general_status(); - do { - io_seproxyhal_spi_recv(G_io_seproxyhal_spi_buffer, sizeof(G_io_seproxyhal_spi_buffer), 0); - // check for reply timeout (when asynch reply (over hid or u2f for example)) - // this case shall be covered by usb_ep_timeout but is not, investigate that - if (G_io_app.ms >= timeout_ms) { - THROW(EXCEPTION_IO_RESET); + // perform reset after io exchange + if (channel & IO_RESET_AFTER_REPLIED) { + // The error cast is retrocompatible with the previous value. + os_sched_exit((bolos_task_status_t) EXCEPTION_IO_RESET); + // reset(); + } } - // avoid a general status to be replied - io_seproxyhal_handle_event(); - } while (io_seproxyhal_spi_is_status_sent()); - } - // reset apdu state - G_io_app.apdu_state = APDU_IDLE; - G_io_app.apdu_media = IO_APDU_MEDIA_NONE; - - G_io_app.apdu_length = 0; - // continue sending commands, don't issue status yet - if (channel & IO_RETURN_AFTER_TX) { - return 0; - } - // acknowledge the write request (general status OK) and no more command to follow (wait until another APDU container is received to continue unwrapping) - io_seproxyhal_general_status(); - break; - } - - // perform reset after io exchange - if (channel & IO_RESET_AFTER_REPLIED) { - // The error cast is retrocompatible with the previous value. - os_sched_exit((bolos_task_status_t)EXCEPTION_IO_RESET); - //reset(); - } - } - - if (!(channel&IO_ASYNCH_REPLY)) { + if (!(channel & IO_ASYNCH_REPLY)) { + // already received the data of the apdu when received the whole apdu + if ((channel & (CHANNEL_APDU | IO_RECEIVE_DATA)) + == (CHANNEL_APDU | IO_RECEIVE_DATA)) { + // return apdu data - header + return G_io_app.apdu_length - 5; + } - // already received the data of the apdu when received the whole apdu - if ((channel & (CHANNEL_APDU|IO_RECEIVE_DATA)) == (CHANNEL_APDU|IO_RECEIVE_DATA)) { - // return apdu data - header - return G_io_app.apdu_length-5; - } + // reply has ended, proceed to next apdu reception (reset status only after asynch + // reply) + G_io_app.apdu_state = APDU_IDLE; + G_io_app.apdu_media = IO_APDU_MEDIA_NONE; + } - // reply has ended, proceed to next apdu reception (reset status only after asynch reply) - G_io_app.apdu_state = APDU_IDLE; - G_io_app.apdu_media = IO_APDU_MEDIA_NONE; - } + // reset the received apdu length + G_io_app.apdu_length = 0; + + // ensure ready to receive an event (after an apdu processing with asynch flag, it may + // occur if the channel is not correctly managed) + + // until a new whole CAPDU is received + for (;;) { + io_seproxyhal_general_status(); + // wait until a SPI packet is available + // NOTE: on ST31, dual wait ISO & RF (ISO instead of SPI) + rx_len = io_seproxyhal_spi_recv( + G_io_seproxyhal_spi_buffer, sizeof(G_io_seproxyhal_spi_buffer), 0); + + // can't process split TLV, continue + if (rx_len < 3 + || rx_len + != U2(G_io_seproxyhal_spi_buffer[1], G_io_seproxyhal_spi_buffer[2]) + + 3U) { + LOG("invalid TLV format\n"); + G_io_app.apdu_state = APDU_IDLE; + G_io_app.apdu_length = 0; + continue; + } - // reset the received apdu length - G_io_app.apdu_length = 0; + io_seproxyhal_handle_event(); - // ensure ready to receive an event (after an apdu processing with asynch flag, it may occur if the channel is not correctly managed) - - // until a new whole CAPDU is received - for (;;) { - io_seproxyhal_general_status(); - // wait until a SPI packet is available - // NOTE: on ST31, dual wait ISO & RF (ISO instead of SPI) - rx_len = io_seproxyhal_spi_recv(G_io_seproxyhal_spi_buffer, sizeof(G_io_seproxyhal_spi_buffer), 0); - - // can't process split TLV, continue - if (rx_len < 3 || rx_len != U2(G_io_seproxyhal_spi_buffer[1],G_io_seproxyhal_spi_buffer[2])+3U) { - LOG("invalid TLV format\n"); - G_io_app.apdu_state = APDU_IDLE; - G_io_app.apdu_length = 0; - continue; - } - - io_seproxyhal_handle_event(); - - // An apdu has been received asynchronously. - if (G_io_app.apdu_state != APDU_IDLE && G_io_app.apdu_length > 0) { - // for Bolos UX and apps, answer SWO_SEC_PIN_15 as soon as PIN has been set and PIN is not validated - if (os_perso_is_pin_set() == BOLOS_TRUE && os_global_pin_is_validated() != BOLOS_TRUE) { - tx_len = 0; - G_io_apdu_buffer[(tx_len)++] = (SWO_SEC_PIN_15 >> 8) & 0xFF; - G_io_apdu_buffer[(tx_len)++] = (SWO_SEC_PIN_15) & 0xFF; - channel &= ~IO_FLAGS; - goto reply_apdu; - } + // An apdu has been received asynchronously. + if (G_io_app.apdu_state != APDU_IDLE && G_io_app.apdu_length > 0) { + // for Bolos UX and apps, answer SWO_SEC_PIN_15 as soon as PIN has been set and + // PIN is not validated + if (os_perso_is_pin_set() == BOLOS_TRUE + && os_global_pin_is_validated() != BOLOS_TRUE) { + tx_len = 0; + G_io_apdu_buffer[(tx_len)++] = (SWO_SEC_PIN_15 >> 8) & 0xFF; + G_io_apdu_buffer[(tx_len)++] = (SWO_SEC_PIN_15) &0xFF; + channel &= ~IO_FLAGS; + goto reply_apdu; + } #if !defined(HAVE_BOLOS_NO_DEFAULT_APDU) - // If a default command is received and processed within this call, - // then we send the answer. - if (io_process_default_apdus(&channel, &tx_len) == BOLOS_TRUE) { - goto reply_apdu; - } -#endif // ! HAVE_BOLOS_NO_DEFAULT_APDU + // If a default command is received and processed within this call, + // then we send the answer. + if (io_process_default_apdus(&channel, &tx_len) == BOLOS_TRUE) { + goto reply_apdu; + } +#endif // ! HAVE_BOLOS_NO_DEFAULT_APDU + + return G_io_app.apdu_length; + } + } + break; - return G_io_app.apdu_length; - } + default: + return io_exchange_al(channel, tx_len); } - break; - - default: - return io_exchange_al(channel, tx_len); - } } -unsigned int os_io_seph_recv_and_process(unsigned int dont_process_ux_events) { - // send general status before receiving next event - io_seproxyhal_general_status(); +unsigned int os_io_seph_recv_and_process(unsigned int dont_process_ux_events) +{ + // send general status before receiving next event + io_seproxyhal_general_status(); + + io_seproxyhal_spi_recv(G_io_seproxyhal_spi_buffer, sizeof(G_io_seproxyhal_spi_buffer), 0); - io_seproxyhal_spi_recv(G_io_seproxyhal_spi_buffer, sizeof(G_io_seproxyhal_spi_buffer), 0); + switch (G_io_seproxyhal_spi_buffer[0]) { + case SEPROXYHAL_TAG_FINGER_EVENT: + case SEPROXYHAL_TAG_BUTTON_PUSH_EVENT: + case SEPROXYHAL_TAG_TICKER_EVENT: + case SEPROXYHAL_TAG_DISPLAY_PROCESSED_EVENT: + case SEPROXYHAL_TAG_STATUS_EVENT: + // perform UX event on these ones, don't process as an IO event + if (dont_process_ux_events) { + return 0; + } + FALL_THROUGH; - switch (G_io_seproxyhal_spi_buffer[0]) { - case SEPROXYHAL_TAG_FINGER_EVENT: - case SEPROXYHAL_TAG_BUTTON_PUSH_EVENT: - case SEPROXYHAL_TAG_TICKER_EVENT: - case SEPROXYHAL_TAG_DISPLAY_PROCESSED_EVENT: - case SEPROXYHAL_TAG_STATUS_EVENT: - // perform UX event on these ones, don't process as an IO event - if (dont_process_ux_events) { - return 0; - } - FALL_THROUGH; - - default: - // if malformed, then a stall is likely to occur - if (io_seproxyhal_handle_event()) { - return 1; - } - } - return 0; + default: + // if malformed, then a stall is likely to occur + if (io_seproxyhal_handle_event()) { + return 1; + } + } + return 0; } #if !defined(APP_UX) -unsigned int os_ux_blocking(bolos_ux_params_t* params) { - unsigned int ret; - - // until a real status is returned - os_ux(params); - ret = os_sched_last_status(TASK_BOLOS_UX); - while(ret == BOLOS_UX_IGNORE - || ret == BOLOS_UX_CONTINUE) { - // if the IO task is not running, then need to pump events manually - if (os_sched_is_running(TASK_SUBTASKS_START) != BOLOS_TRUE) { - // send general status before receiving next event - io_seproxyhal_general_status(); - io_seproxyhal_spi_recv(G_io_seproxyhal_spi_buffer, sizeof(G_io_seproxyhal_spi_buffer), 0); - io_event(0); - } - else - { - // wait until UX takes some process time and update it's status - os_sched_yield(BOLOS_UX_OK); - } - // only retrieve the current UX state +unsigned int os_ux_blocking(bolos_ux_params_t *params) +{ + unsigned int ret; + + // until a real status is returned + os_ux(params); ret = os_sched_last_status(TASK_BOLOS_UX); - } + while (ret == BOLOS_UX_IGNORE || ret == BOLOS_UX_CONTINUE) { + // if the IO task is not running, then need to pump events manually + if (os_sched_is_running(TASK_SUBTASKS_START) != BOLOS_TRUE) { + // send general status before receiving next event + io_seproxyhal_general_status(); + io_seproxyhal_spi_recv( + G_io_seproxyhal_spi_buffer, sizeof(G_io_seproxyhal_spi_buffer), 0); + io_event(0); + } + else { + // wait until UX takes some process time and update it's status + os_sched_yield(BOLOS_UX_OK); + } + // only retrieve the current UX state + ret = os_sched_last_status(TASK_BOLOS_UX); + } - return ret; + return ret; } -#endif // !defined(APP_UX) +#endif // !defined(APP_UX) #ifdef HAVE_PRINTF -void mcu_usb_prints(const char* str, unsigned int charcount) { - unsigned char buf[4]; +void mcu_usb_prints(const char *str, unsigned int charcount) +{ + unsigned char buf[4]; #ifdef TARGET_NANOS - buf[0] = SEPROXYHAL_TAG_PRINTF_STATUS; + buf[0] = SEPROXYHAL_TAG_PRINTF_STATUS; #else - buf[0] = SEPROXYHAL_TAG_PRINTF; + buf[0] = SEPROXYHAL_TAG_PRINTF; #endif - buf[1] = charcount >> 8; - buf[2] = charcount; - io_seproxyhal_spi_send(buf, 3); - io_seproxyhal_spi_send((const uint8_t *) str, charcount); + buf[1] = charcount >> 8; + buf[2] = charcount; + io_seproxyhal_spi_send(buf, 3); + io_seproxyhal_spi_send((const uint8_t *) str, charcount); } -#endif // HAVE_PRINTF +#endif // HAVE_PRINTF -void io_seproxyhal_io_heartbeat(void) { - io_seproxyhal_general_status(); - do { - io_seproxyhal_spi_recv(G_io_seproxyhal_spi_buffer, sizeof(G_io_seproxyhal_spi_buffer), 0); - // avoid a general status to be replied - if(G_io_seproxyhal_spi_buffer[0] != SEPROXYHAL_TAG_TICKER_EVENT) { - io_seproxyhal_handle_event(); - } - } while (io_seproxyhal_spi_is_status_sent()); +void io_seproxyhal_io_heartbeat(void) +{ + io_seproxyhal_general_status(); + do { + io_seproxyhal_spi_recv(G_io_seproxyhal_spi_buffer, sizeof(G_io_seproxyhal_spi_buffer), 0); + // avoid a general status to be replied + if (G_io_seproxyhal_spi_buffer[0] != SEPROXYHAL_TAG_TICKER_EVENT) { + io_seproxyhal_handle_event(); + } + } while (io_seproxyhal_spi_is_status_sent()); } -#endif // OS_IO_SEPROXYHAL +#endif // OS_IO_SEPROXYHAL diff --git a/src/os_io_task.c b/src/os_io_task.c index ea42d6466..bdb4feaef 100644 --- a/src/os_io_task.c +++ b/src/os_io_task.c @@ -9,85 +9,95 @@ #ifdef HAVE_BLE #include "ledger_ble.h" bolos_ux_asynch_callback_t G_io_asynch_ux_callback; -#endif // HAVE_BLE +#endif // HAVE_BLE #ifdef HAVE_BOLOS #ifdef HAVE_BLE -# if (IO_SEPROXYHAL_BUFFER_SIZE_B < 192) && (defined(BOLOS_RELEASE) || !defined(DEBUG_VARIABLE_SPI_SIZE)) -# error IO_SEPROXYHAL_BUFFER_SIZE_B size is invalid -# endif // (IO_SEPROXYHAL_BUFFER_SIZE_B < 192) && (defined(BOLOS_RELEASE) || !defined(DEBUG_VARIABLE_SPI_SIZE)) -#else // !HAVE_BLE -# if (IO_SEPROXYHAL_BUFFER_SIZE_B != 128) && (defined(BOLOS_RELEASE) || !defined(DEBUG_VARIABLE_SPI_SIZE)) -# error IO_SEPROXYHAL_BUFFER_SIZE_B size is invalid -# endif // (IO_SEPROXYHAL_BUFFER_SIZE_B != 128) && (defined(BOLOS_RELEASE) || !defined(DEBUG_VARIABLE_SPI_SIZE)) -#endif // !HAVE_BLE +#if (IO_SEPROXYHAL_BUFFER_SIZE_B < 192) \ + && (defined(BOLOS_RELEASE) || !defined(DEBUG_VARIABLE_SPI_SIZE)) +#error IO_SEPROXYHAL_BUFFER_SIZE_B size is invalid +#endif // (IO_SEPROXYHAL_BUFFER_SIZE_B < 192) && (defined(BOLOS_RELEASE) || + // !defined(DEBUG_VARIABLE_SPI_SIZE)) +#else // !HAVE_BLE +#if (IO_SEPROXYHAL_BUFFER_SIZE_B != 128) \ + && (defined(BOLOS_RELEASE) || !defined(DEBUG_VARIABLE_SPI_SIZE)) +#error IO_SEPROXYHAL_BUFFER_SIZE_B size is invalid +#endif // (IO_SEPROXYHAL_BUFFER_SIZE_B != 128) && (defined(BOLOS_RELEASE) || + // !defined(DEBUG_VARIABLE_SPI_SIZE)) +#endif // !HAVE_BLE // Buffer dedicated to the MCU <-> SE data transfer. unsigned char G_io_seproxyhal_spi_buffer[IO_SEPROXYHAL_BUFFER_SIZE_B]; io_seph_app_t G_io_app; -#endif // HAVE_BOLOS +#endif // HAVE_BOLOS #ifdef HAVE_IO_TASK -void io_start(void) { -#else // HAVE_IO_TASK -void bolos_init_ios(void) { -#endif // HAVE_IO_TASK +void io_start(void) +{ +#else // HAVE_IO_TASK +void bolos_init_ios(void) +{ +#endif // HAVE_IO_TASK #ifdef OS_IO_SEPROXYHAL - io_seproxyhal_init(); + io_seproxyhal_init(); #endif #ifdef HAVE_IO_USB - USB_power(0); + USB_power(0); #endif #ifdef HAVE_BLE - memset(&G_io_asynch_ux_callback, 0, sizeof(G_io_asynch_ux_callback)); - LEDGER_BLE_init(); -#endif // HAVE_BLE + memset(&G_io_asynch_ux_callback, 0, sizeof(G_io_asynch_ux_callback)); + LEDGER_BLE_init(); +#endif // HAVE_BLE #ifdef OS_IO_SEPROXYHAL - io_seproxyhal_init(); + io_seproxyhal_init(); #endif #ifdef HAVE_IO_USB - USB_power(1); + USB_power(1); #endif } - #ifdef HAVE_IO_TASK -void io_process(void) { - for (;;) { - if (!(G_io_app.io_flags & IO_FINISHED)) { - G_io_app.apdu_length = io_exchange(CHANNEL_APDU | G_io_app.io_flags, G_io_app.apdu_length); - // mark IO as ended - G_io_app.io_flags |= IO_FINISHED; - } - else { - // pump packets (process all through handle_events) - os_io_seph_recv_and_process(0); +void io_process(void) +{ + for (;;) { + if (!(G_io_app.io_flags & IO_FINISHED)) { + G_io_app.apdu_length + = io_exchange(CHANNEL_APDU | G_io_app.io_flags, G_io_app.apdu_length); + // mark IO as ended + G_io_app.io_flags |= IO_FINISHED; + } + else { + // pump packets (process all through handle_events) + os_io_seph_recv_and_process(0); + } + // we have finished our call, notify the other tasks + os_sched_yield(BOLOS_TRUE); } - // we have finished our call, notify the other tasks - os_sched_yield(BOLOS_TRUE); - } } -void io_task(void) { - for(;;) { - BEGIN_TRY { - TRY { - io_start(); - io_process(); - } - CATCH_ALL { - // any error leading here is triggering an IO stack reset - os_sched_yield(EXCEPTION_IO_RESET); - } - FINALLY { - } +void io_task(void) +{ + for (;;) { + BEGIN_TRY + { + TRY + { + io_start(); + io_process(); + } + CATCH_ALL + { + // any error leading here is triggering an IO stack reset + os_sched_yield(EXCEPTION_IO_RESET); + } + FINALLY {} + } + END_TRY; } - END_TRY; - } } -#endif // HAVE_IO_TASK +#endif // HAVE_IO_TASK diff --git a/src/os_io_usb.c b/src/os_io_usb.c index 11f08de74..5af0ee509 100644 --- a/src/os_io_usb.c +++ b/src/os_io_usb.c @@ -1,20 +1,20 @@ /******************************************************************************* -* Ledger Nano S - Secure firmware -* (c) 2022 Ledger -* -* Licensed under the Apache License, Version 2.0 (the "License"); -* you may not use this file except in compliance with the License. -* You may obtain a copy of the License at -* -* http://www.apache.org/licenses/LICENSE-2.0 -* -* Unless required by applicable law or agreed to in writing, software -* distributed under the License is distributed on an "AS IS" BASIS, -* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -* See the License for the specific language governing permissions and -* limitations under the License. -********************************************************************************/ + * Ledger Nano S - Secure firmware + * (c) 2022 Ledger + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT 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 "os_io_usb.h" #include "os_utils.h" @@ -26,42 +26,48 @@ // usb endpoint buffer unsigned char G_io_usb_ep_buffer[MAX(USB_SEGMENT_SIZE, BLE_SEGMENT_SIZE)]; -uint16_t io_seproxyhal_get_ep_rx_size(uint8_t epnum) { - if ((epnum & 0x7F) < IO_USB_MAX_ENDPOINTS) { - return G_io_app.usb_ep_xfer_len[epnum&0x7F]; - } - return 0; +uint16_t io_seproxyhal_get_ep_rx_size(uint8_t epnum) +{ + if ((epnum & 0x7F) < IO_USB_MAX_ENDPOINTS) { + return G_io_app.usb_ep_xfer_len[epnum & 0x7F]; + } + return 0; } #ifndef IO_RAPDU_TRANSMIT_TIMEOUT_MS #define IO_RAPDU_TRANSMIT_TIMEOUT_MS 2000UL -#endif // IO_RAPDU_TRANSMIT_TIMEOUT_MS +#endif // IO_RAPDU_TRANSMIT_TIMEOUT_MS // TODO, refactor this using the USB DataIn event like for the U2F tunnel // TODO add a blocking parameter, for HID KBD sending, or use a USB busy flag per channel to know if // the transfer has been processed or not. and move on to the next transfer on the same endpoint -void io_usb_send_ep(unsigned int ep, unsigned char* buffer, unsigned short length, __attribute__((unused)) unsigned int timeout) { - // won't send if overflowing seproxyhal buffer format - if (length > 255) { - return; - } - - uint8_t buf[6]; - buf[0] = SEPROXYHAL_TAG_USB_EP_PREPARE; - buf[1] = (3+length)>>8; - buf[2] = (3+length); - buf[3] = ep|0x80; - buf[4] = SEPROXYHAL_TAG_USB_EP_PREPARE_DIR_IN; - buf[5] = length; - io_seproxyhal_spi_send(buf, 6); - io_seproxyhal_spi_send(buffer, length); - // setup timeout of the endpoint - G_io_app.usb_ep_timeouts[ep&0x7F].timeout = IO_RAPDU_TRANSMIT_TIMEOUT_MS; +void io_usb_send_ep(unsigned int ep, + unsigned char *buffer, + unsigned short length, + __attribute__((unused)) unsigned int timeout) +{ + // won't send if overflowing seproxyhal buffer format + if (length > 255) { + return; + } + + uint8_t buf[6]; + buf[0] = SEPROXYHAL_TAG_USB_EP_PREPARE; + buf[1] = (3 + length) >> 8; + buf[2] = (3 + length); + buf[3] = ep | 0x80; + buf[4] = SEPROXYHAL_TAG_USB_EP_PREPARE_DIR_IN; + buf[5] = length; + io_seproxyhal_spi_send(buf, 6); + io_seproxyhal_spi_send(buffer, length); + // setup timeout of the endpoint + G_io_app.usb_ep_timeouts[ep & 0x7F].timeout = IO_RAPDU_TRANSMIT_TIMEOUT_MS; } -void io_usb_send_apdu_data(unsigned char* buffer, unsigned short length) { - // wait for 20 events before hanging up and timeout (~2 seconds of timeout) - io_usb_send_ep(0x82, buffer, length, 20); +void io_usb_send_apdu_data(unsigned char *buffer, unsigned short length) +{ + // wait for 20 events before hanging up and timeout (~2 seconds of timeout) + io_usb_send_ep(0x82, buffer, length, 20); } /** @@ -82,205 +88,225 @@ void io_usb_send_apdu_data(unsigned char* buffer, unsigned short length) { * * Filler only allowed at the end of the last hid report of a apdu chain in each direction. * - * APDU are using either standard or extended header. up to the application to check the total received length and the lc field + * APDU are using either standard or extended header. up to the application to check the total + * received length and the lc field * * Tags: - * Direction:Host>Token T:0x00 V:no Get protocol version big endian encoded. Replied with a protocol-version. Channel identifier is ignored for this command. - * Direction:Token>Host T:0x00 V:yes protocol-version-4-bytes-big-endian. Channel identifier is ignored for this reply. - * Direction:Host>Token T:0x01 V:no Allocate channel. Replied with a channel identifier. Channel identifier is ignored for this command. - * Direction:Token>Host T:0x01 V:yes channel-identifier-2-bytes. Channel identifier is ignored for this reply. - * Direction:* T:0x02 V:no Ping. replied with a ping. Channel identifier is ignored for this command. - * NOTSUPPORTED Direction:* T:0x03 V:no Abort. replied with an abort if accepted, else not replied. - * Direction:* T:0x05 V= APDU (command/response) packet. + * Direction:Host>Token T:0x00 V:no Get protocol version big endian encoded. Replied with a + * protocol-version. Channel identifier is ignored for this command. Direction:Token>Host T:0x00 + * V:yes protocol-version-4-bytes-big-endian. Channel identifier is ignored for this reply. + * Direction:Host>Token T:0x01 V:no Allocate channel. Replied with a channel identifier. Channel + * identifier is ignored for this command. Direction:Token>Host T:0x01 V:yes + * channel-identifier-2-bytes. Channel identifier is ignored for this reply. Direction:* T:0x02 V:no + * Ping. replied with a ping. Channel identifier is ignored for this command. NOTSUPPORTED + * Direction:* T:0x03 V:no Abort. replied with an abort if accepted, else not replied. + * Direction:* T:0x05 V= APDU + * (command/response) packet. */ -volatile unsigned int G_io_usb_hid_total_length; -volatile unsigned int G_io_usb_hid_channel; -volatile unsigned int G_io_usb_hid_remaining_length; -volatile unsigned int G_io_usb_hid_sequence_number; -static uint8_t * G_io_usb_hid_current_buffer; - -io_usb_hid_receive_status_t io_usb_hid_receive (io_send_t sndfct, unsigned char* buffer, unsigned short l, apdu_buffer_t * apdu_buffer) { - uint8_t * apdu_buf; - uint16_t apdu_buf_len; +volatile unsigned int G_io_usb_hid_total_length; +volatile unsigned int G_io_usb_hid_channel; +volatile unsigned int G_io_usb_hid_remaining_length; +volatile unsigned int G_io_usb_hid_sequence_number; +static uint8_t *G_io_usb_hid_current_buffer; + +io_usb_hid_receive_status_t io_usb_hid_receive(io_send_t sndfct, + unsigned char *buffer, + unsigned short l, + apdu_buffer_t *apdu_buffer) +{ + uint8_t *apdu_buf; + uint16_t apdu_buf_len; #ifndef HAVE_LOCAL_APDU_BUFFER - if (apdu_buffer == NULL) { - apdu_buf = G_io_apdu_buffer; - apdu_buf_len = sizeof(G_io_apdu_buffer); - } - else -#endif // HAVE_LOCAL_APDU_BUFFER - { - apdu_buf = apdu_buffer->buf; - apdu_buf_len = apdu_buffer->len; - } - - // avoid over/under flows - if (buffer != G_io_usb_ep_buffer) { - memset(G_io_usb_ep_buffer, 0, sizeof(G_io_usb_ep_buffer)); - memmove(G_io_usb_ep_buffer, buffer, MIN(l, sizeof(G_io_usb_ep_buffer))); - } - - // process the chunk content - switch(G_io_usb_ep_buffer[2]) { - case 0x05: - // ensure sequence idx is 0 for the first chunk ! - if ((unsigned int)U2BE(G_io_usb_ep_buffer, 3) != (unsigned int)G_io_usb_hid_sequence_number) { - // ignore packet - goto apdu_reset; + if (apdu_buffer == NULL) { + apdu_buf = G_io_apdu_buffer; + apdu_buf_len = sizeof(G_io_apdu_buffer); } - // cid, tag, seq - l -= 2+1+2; - - // append the received chunk to the current command apdu - if (G_io_usb_hid_sequence_number == 0) { - /// This is the apdu first chunk - // total apdu size to receive - G_io_usb_hid_total_length = U2BE(G_io_usb_ep_buffer, 5); //(G_io_usb_ep_buffer[5]<<8)+(G_io_usb_ep_buffer[6]&0xFF); - // check for invalid length encoding (more data in chunk that announced in the total apdu) - if (G_io_usb_hid_total_length > (uint32_t)apdu_buf_len) { - goto apdu_reset; - } - // seq and total length - l -= 2; - // compute remaining size to receive - G_io_usb_hid_remaining_length = G_io_usb_hid_total_length; - G_io_usb_hid_current_buffer = apdu_buf; - - // retain the channel id to use for the reply - G_io_usb_hid_channel = U2BE(G_io_usb_ep_buffer, 0); - - if (l > G_io_usb_hid_remaining_length) { - l = G_io_usb_hid_remaining_length; - } - - if (l > sizeof(G_io_usb_ep_buffer) - 7) { - l = sizeof(G_io_usb_ep_buffer) - 7; - } - - // copy data - memmove((void*)G_io_usb_hid_current_buffer, G_io_usb_ep_buffer+7, l); + else +#endif // HAVE_LOCAL_APDU_BUFFER + { + apdu_buf = apdu_buffer->buf; + apdu_buf_len = apdu_buffer->len; } - else { - // check for invalid length encoding (more data in chunk that announced in the total apdu) - if (l > G_io_usb_hid_remaining_length) { - l = G_io_usb_hid_remaining_length; - } - - if (l > sizeof(G_io_usb_ep_buffer) - 5) { - l = sizeof(G_io_usb_ep_buffer) - 5; - } - - /// This is a following chunk - // append content - memmove((void*)G_io_usb_hid_current_buffer, G_io_usb_ep_buffer+5, l); + + // avoid over/under flows + if (buffer != G_io_usb_ep_buffer) { + memset(G_io_usb_ep_buffer, 0, sizeof(G_io_usb_ep_buffer)); + memmove(G_io_usb_ep_buffer, buffer, MIN(l, sizeof(G_io_usb_ep_buffer))); + } + + // process the chunk content + switch (G_io_usb_ep_buffer[2]) { + case 0x05: + // ensure sequence idx is 0 for the first chunk ! + if ((unsigned int) U2BE(G_io_usb_ep_buffer, 3) + != (unsigned int) G_io_usb_hid_sequence_number) { + // ignore packet + goto apdu_reset; + } + // cid, tag, seq + l -= 2 + 1 + 2; + + // append the received chunk to the current command apdu + if (G_io_usb_hid_sequence_number == 0) { + /// This is the apdu first chunk + // total apdu size to receive + G_io_usb_hid_total_length + = U2BE(G_io_usb_ep_buffer, + 5); //(G_io_usb_ep_buffer[5]<<8)+(G_io_usb_ep_buffer[6]&0xFF); + // check for invalid length encoding (more data in chunk that announced in the total + // apdu) + if (G_io_usb_hid_total_length > (uint32_t) apdu_buf_len) { + goto apdu_reset; + } + // seq and total length + l -= 2; + // compute remaining size to receive + G_io_usb_hid_remaining_length = G_io_usb_hid_total_length; + G_io_usb_hid_current_buffer = apdu_buf; + + // retain the channel id to use for the reply + G_io_usb_hid_channel = U2BE(G_io_usb_ep_buffer, 0); + + if (l > G_io_usb_hid_remaining_length) { + l = G_io_usb_hid_remaining_length; + } + + if (l > sizeof(G_io_usb_ep_buffer) - 7) { + l = sizeof(G_io_usb_ep_buffer) - 7; + } + + // copy data + memmove((void *) G_io_usb_hid_current_buffer, G_io_usb_ep_buffer + 7, l); + } + else { + // check for invalid length encoding (more data in chunk that announced in the total + // apdu) + if (l > G_io_usb_hid_remaining_length) { + l = G_io_usb_hid_remaining_length; + } + + if (l > sizeof(G_io_usb_ep_buffer) - 5) { + l = sizeof(G_io_usb_ep_buffer) - 5; + } + + /// This is a following chunk + // append content + memmove((void *) G_io_usb_hid_current_buffer, G_io_usb_ep_buffer + 5, l); + } + // factorize (f) + G_io_usb_hid_current_buffer += l; + G_io_usb_hid_remaining_length -= l; + G_io_usb_hid_sequence_number++; + break; + + case 0x00: // get version ID + // do not reset the current apdu reception if any + memset(G_io_usb_ep_buffer + 3, 0, 4); // PROTOCOL VERSION is 0 + // send the response + sndfct(G_io_usb_ep_buffer, IO_HID_EP_LENGTH); + // await for the next chunk + goto apdu_reset; + + case 0x01: // ALLOCATE CHANNEL + // do not reset the current apdu reception if any + cx_rng_no_throw(G_io_usb_ep_buffer + 3, 4); + // send the response + sndfct(G_io_usb_ep_buffer, IO_HID_EP_LENGTH); + // await for the next chunk + goto apdu_reset; + + case 0x02: // ECHO|PING + // do not reset the current apdu reception if any + // send the response + sndfct(G_io_usb_ep_buffer, IO_HID_EP_LENGTH); + // await for the next chunk + goto apdu_reset; + } + + // if more data to be received, notify it + if (G_io_usb_hid_remaining_length) { + return IO_USB_APDU_MORE_DATA; } - // factorize (f) - G_io_usb_hid_current_buffer += l; - G_io_usb_hid_remaining_length -= l; - G_io_usb_hid_sequence_number++; - break; - - case 0x00: // get version ID - // do not reset the current apdu reception if any - memset(G_io_usb_ep_buffer+3, 0, 4); // PROTOCOL VERSION is 0 - // send the response - sndfct(G_io_usb_ep_buffer, IO_HID_EP_LENGTH); - // await for the next chunk - goto apdu_reset; - - case 0x01: // ALLOCATE CHANNEL - // do not reset the current apdu reception if any - cx_rng_no_throw(G_io_usb_ep_buffer+3, 4); - // send the response - sndfct(G_io_usb_ep_buffer, IO_HID_EP_LENGTH); - // await for the next chunk - goto apdu_reset; - - case 0x02: // ECHO|PING - // do not reset the current apdu reception if any - // send the response - sndfct(G_io_usb_ep_buffer, IO_HID_EP_LENGTH); - // await for the next chunk - goto apdu_reset; - } - - // if more data to be received, notify it - if (G_io_usb_hid_remaining_length) { - return IO_USB_APDU_MORE_DATA; - } - - // reset sequence number for next exchange - io_usb_hid_init(); - return IO_USB_APDU_RECEIVED; + + // reset sequence number for next exchange + io_usb_hid_init(); + return IO_USB_APDU_RECEIVED; apdu_reset: - io_usb_hid_init(); - return IO_USB_APDU_RESET; + io_usb_hid_init(); + return IO_USB_APDU_RESET; } -void io_usb_hid_init(void) { - G_io_usb_hid_sequence_number = 0; - G_io_usb_hid_remaining_length = 0; - G_io_usb_hid_current_buffer = NULL; +void io_usb_hid_init(void) +{ + G_io_usb_hid_sequence_number = 0; + G_io_usb_hid_remaining_length = 0; + G_io_usb_hid_current_buffer = NULL; } /** * sent the next io_usb_hid transport chunk (rx on the host, tx on the device) */ -void io_usb_hid_sent(io_send_t sndfct) { - unsigned int l; - - // only prepare next chunk if some data to be sent remain - if (G_io_usb_hid_remaining_length && G_io_usb_hid_current_buffer) { - // fill the chunk - memset(G_io_usb_ep_buffer, 0, sizeof(G_io_usb_ep_buffer)); - - // keep the channel identifier - G_io_usb_ep_buffer[0] = (G_io_usb_hid_channel>>8)&0xFF; - G_io_usb_ep_buffer[1] = G_io_usb_hid_channel&0xFF; - G_io_usb_ep_buffer[2] = 0x05; - G_io_usb_ep_buffer[3] = G_io_usb_hid_sequence_number>>8; - G_io_usb_ep_buffer[4] = G_io_usb_hid_sequence_number; - - if (G_io_usb_hid_sequence_number == 0) { - l = ((G_io_usb_hid_remaining_length>IO_HID_EP_LENGTH-7) ? IO_HID_EP_LENGTH-7 : G_io_usb_hid_remaining_length); - G_io_usb_ep_buffer[5] = G_io_usb_hid_remaining_length>>8; - G_io_usb_ep_buffer[6] = G_io_usb_hid_remaining_length; - memmove(G_io_usb_ep_buffer+7, (const void*)G_io_usb_hid_current_buffer, l); - G_io_usb_hid_current_buffer += l; - G_io_usb_hid_remaining_length -= l; +void io_usb_hid_sent(io_send_t sndfct) +{ + unsigned int l; + + // only prepare next chunk if some data to be sent remain + if (G_io_usb_hid_remaining_length && G_io_usb_hid_current_buffer) { + // fill the chunk + memset(G_io_usb_ep_buffer, 0, sizeof(G_io_usb_ep_buffer)); + + // keep the channel identifier + G_io_usb_ep_buffer[0] = (G_io_usb_hid_channel >> 8) & 0xFF; + G_io_usb_ep_buffer[1] = G_io_usb_hid_channel & 0xFF; + G_io_usb_ep_buffer[2] = 0x05; + G_io_usb_ep_buffer[3] = G_io_usb_hid_sequence_number >> 8; + G_io_usb_ep_buffer[4] = G_io_usb_hid_sequence_number; + + if (G_io_usb_hid_sequence_number == 0) { + l = ((G_io_usb_hid_remaining_length > IO_HID_EP_LENGTH - 7) + ? IO_HID_EP_LENGTH - 7 + : G_io_usb_hid_remaining_length); + G_io_usb_ep_buffer[5] = G_io_usb_hid_remaining_length >> 8; + G_io_usb_ep_buffer[6] = G_io_usb_hid_remaining_length; + memmove(G_io_usb_ep_buffer + 7, (const void *) G_io_usb_hid_current_buffer, l); + G_io_usb_hid_current_buffer += l; + G_io_usb_hid_remaining_length -= l; + } + else { + l = ((G_io_usb_hid_remaining_length > IO_HID_EP_LENGTH - 5) + ? IO_HID_EP_LENGTH - 5 + : G_io_usb_hid_remaining_length); + memmove(G_io_usb_ep_buffer + 5, (const void *) G_io_usb_hid_current_buffer, l); + G_io_usb_hid_current_buffer += l; + G_io_usb_hid_remaining_length -= l; + } + // prepare next chunk numbering + G_io_usb_hid_sequence_number++; + // send the chunk + // always padded (USB HID transport) :) + sndfct(G_io_usb_ep_buffer, sizeof(G_io_usb_ep_buffer)); } + // cleanup when everything has been sent (ack for the last sent usb in packet) else { - l = ((G_io_usb_hid_remaining_length>IO_HID_EP_LENGTH-5) ? IO_HID_EP_LENGTH-5 : G_io_usb_hid_remaining_length); - memmove(G_io_usb_ep_buffer+5, (const void*)G_io_usb_hid_current_buffer, l); - G_io_usb_hid_current_buffer += l; - G_io_usb_hid_remaining_length -= l; - } - // prepare next chunk numbering - G_io_usb_hid_sequence_number++; - // send the chunk - // always padded (USB HID transport) :) - sndfct(G_io_usb_ep_buffer, sizeof(G_io_usb_ep_buffer)); - } - // cleanup when everything has been sent (ack for the last sent usb in packet) - else { - io_usb_hid_init(); + io_usb_hid_init(); - // we sent the whole response - G_io_app.apdu_state = APDU_IDLE; - } + // we sent the whole response + G_io_app.apdu_state = APDU_IDLE; + } } -void io_usb_hid_send(io_send_t sndfct, unsigned short sndlength, unsigned char * apdu_buffer) { - // perform send - if (sndlength) { - G_io_usb_hid_sequence_number = 0; - G_io_usb_hid_current_buffer = apdu_buffer; - G_io_usb_hid_remaining_length = sndlength; - G_io_usb_hid_total_length = sndlength; - io_usb_hid_sent(sndfct); - } +void io_usb_hid_send(io_send_t sndfct, unsigned short sndlength, unsigned char *apdu_buffer) +{ + // perform send + if (sndlength) { + G_io_usb_hid_sequence_number = 0; + G_io_usb_hid_current_buffer = apdu_buffer; + G_io_usb_hid_remaining_length = sndlength; + G_io_usb_hid_total_length = sndlength; + io_usb_hid_sent(sndfct); + } } -#endif // HAVE_USB_APDU +#endif // HAVE_USB_APDU diff --git a/src/os_printf.c b/src/os_printf.c index fefa90810..197dd7b54 100644 --- a/src/os_printf.c +++ b/src/os_printf.c @@ -1,20 +1,20 @@ /******************************************************************************* -* Ledger Nano S - Secure firmware -* (c) 2022 Ledger -* -* Licensed under the Apache License, Version 2.0 (the "License"); -* you may not use this file except in compliance with the License. -* You may obtain a copy of the License at -* -* http://www.apache.org/licenses/LICENSE-2.0 -* -* Unless required by applicable law or agreed to in writing, software -* distributed under the License is distributed on an "AS IS" BASIS, -* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -* See the License for the specific language governing permissions and -* limitations under the License. -********************************************************************************/ + * Ledger Nano S - Secure firmware + * (c) 2022 Ledger + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT 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 @@ -22,36 +22,66 @@ #include "os_math.h" #if defined(HAVE_BOLOS) -# include "bolos_target.h" -#endif // HAVE_BOLOS +#include "bolos_target.h" +#endif // HAVE_BOLOS #if defined(HAVE_PRINTF) || defined(HAVE_SPRINTF) static const char g_pcHex[] = { - '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'a', 'b', 'c', 'd', 'e', 'f', + '0', + '1', + '2', + '3', + '4', + '5', + '6', + '7', + '8', + '9', + 'a', + 'b', + 'c', + 'd', + 'e', + 'f', }; static const char g_pcHex_cap[] = { - '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'A', 'B', 'C', 'D', 'E', 'F', + '0', + '1', + '2', + '3', + '4', + '5', + '6', + '7', + '8', + '9', + 'A', + 'B', + 'C', + 'D', + 'E', + 'F', }; -#endif // defined(HAVE_PRINTF) || defined(HAVE_SPRINTF) +#endif // defined(HAVE_PRINTF) || defined(HAVE_SPRINTF) #ifdef HAVE_PRINTF #include "os_io_seproxyhal.h" -void screen_printf(const char* format, ...) __attribute__ ((weak, alias ("mcu_usb_printf"))); - -void mcu_usb_printf(const char* format, ...) { +void screen_printf(const char *format, ...) __attribute__((weak, alias("mcu_usb_printf"))); +void mcu_usb_printf(const char *format, ...) +{ unsigned long ulIdx, ulValue, ulPos, ulCount, ulBase, ulNeg, ulStrlen, ulCap; - char *pcStr, pcBuf[16], cFill; - va_list vaArgP; - char cStrlenSet; + char *pcStr, pcBuf[16], cFill; + va_list vaArgP; + char cStrlenSet; // // Check the arguments. // - if(format == 0) { - return; + if (format == 0) { + return; } // @@ -62,14 +92,11 @@ void mcu_usb_printf(const char* format, ...) { // // Loop while there are more characters in the string. // - while(*format) - { + while (*format) { // // Find the first non-% character, or the end of the string. // - for(ulIdx = 0; (format[ulIdx] != '%') && (format[ulIdx] != '\0'); - ulIdx++) - { + for (ulIdx = 0; (format[ulIdx] != '%') && (format[ulIdx] != '\0'); ulIdx++) { } // @@ -85,8 +112,7 @@ void mcu_usb_printf(const char* format, ...) { // // See if the next character is a %. // - if(*format == '%') - { + if (*format == '%') { // // Skip the %. // @@ -96,25 +122,24 @@ void mcu_usb_printf(const char* format, ...) { // Set the digit count to zero, and the fill character to space // (i.e. to the defaults). // - ulCount = 0; - cFill = ' '; - ulStrlen = 0; + ulCount = 0; + cFill = ' '; + ulStrlen = 0; cStrlenSet = 0; - ulCap = 0; - ulBase = 10; + ulCap = 0; + ulBase = 10; // // It may be necessary to get back here to process more characters. // Goto's aren't pretty, but effective. I feel extremely dirty for // using not one but two of the beasts. // -again: + again: // // Determine how to handle the next character. // - switch(*format++) - { + switch (*format++) { // // Handle the digit characters. // @@ -127,14 +152,12 @@ void mcu_usb_printf(const char* format, ...) { case '6': case '7': case '8': - case '9': - { + case '9': { // // If this is a zero, and it is the first digit, then the // fill character is a zero instead of a space. // - if((format[-1] == '0') && (ulCount == 0)) - { + if ((format[-1] == '0') && (ulCount == 0)) { cFill = '0'; } @@ -153,8 +176,7 @@ void mcu_usb_printf(const char* format, ...) { // // Handle the %c command. // - case 'c': - { + case 'c': { // // Get the value from the varargs. // @@ -163,7 +185,7 @@ void mcu_usb_printf(const char* format, ...) { // // Print out the character. // - mcu_usb_prints((char *)&ulValue, 1); + mcu_usb_prints((char *) &ulValue, 1); // // This command has been handled. @@ -174,8 +196,7 @@ void mcu_usb_printf(const char* format, ...) { // // Handle the %d command. // - case 'd': - { + case 'd': { // // Get the value from the varargs. // @@ -190,20 +211,18 @@ void mcu_usb_printf(const char* format, ...) { // If the value is negative, make it positive and indicate // that a minus sign is needed. // - if((long)ulValue < 0) - { + if ((long) ulValue < 0) { // // Make the value positive. // - ulValue = -(long)ulValue; + ulValue = -(long) ulValue; // // Indicate that the value is negative. // ulNeg = 1; } - else - { + else { // // Indicate that the value is positive so that a minus // sign isn't inserted. @@ -224,60 +243,57 @@ void mcu_usb_printf(const char* format, ...) { // // Handle the %.*s command - // special %.*H or %.*h format to print a given length of hex digits (case: H UPPER, h lower) + // special %.*H or %.*h format to print a given length of hex digits (case: H UPPER, + // h lower) // - case '.': - { - // ensure next char is '*' and next one is 's' - if (format[0] == '*' && (format[1] == 's' || format[1] == 'H' || format[1] == 'h')) { - - // skip '*' char - format++; + case '.': { + // ensure next char is '*' and next one is 's' + if (format[0] == '*' + && (format[1] == 's' || format[1] == 'H' || format[1] == 'h')) { + // skip '*' char + format++; - ulStrlen = va_arg(vaArgP, unsigned long); - cStrlenSet = 1; + ulStrlen = va_arg(vaArgP, unsigned long); + cStrlenSet = 1; - // interpret next char (H/h/s) - goto again; - } + // interpret next char (H/h/s) + goto again; + } - // does not support %.2x for example - goto error; + // does not support %.2x for example + goto error; } - case '*': - { - if (*format == 's' ) { - - ulStrlen = va_arg(vaArgP, unsigned long); - cStrlenSet = 2; - goto again; - } + case '*': { + if (*format == 's') { + ulStrlen = va_arg(vaArgP, unsigned long); + cStrlenSet = 2; + goto again; + } - goto error; + goto error; } - case '-': // -XXs + case '-': // -XXs { - cStrlenSet = 0; - // read a number of space to post pad with ' ' the string to display - goto again; + cStrlenSet = 0; + // read a number of space to post pad with ' ' the string to display + goto again; } // // Handle the %s command. // %H and %h also case 'H': - ulCap = 1; // uppercase base 16 - ulBase = 16; - goto case_s; + ulCap = 1; // uppercase base 16 + ulBase = 16; + goto case_s; case 'h': - ulCap = 0; - ulBase = 16; // lowercase base 16 - goto case_s; + ulCap = 0; + ulBase = 16; // lowercase base 16 + goto case_s; case 's': - case_s: - { + case_s : { // // Get the string pointer from the varargs. // @@ -286,81 +302,78 @@ void mcu_usb_printf(const char* format, ...) { // // Determine the length of the string. (if not specified using .*) // - switch(cStrlenSet) { - // compute length with strlen - case 0: - for(ulIdx = 0; pcStr[ulIdx] != '\0'; ulIdx++) - { - } - break; - - // use given length - case 1: - ulIdx = ulStrlen; - break; - - // printout prepad - case 2: - // if string is empty, then, ' ' padding - if (pcStr[0] == '\0') { - - // pad with ulStrlen white spaces - do { - mcu_usb_prints(" ", 1); - } while(ulStrlen-- > 0); - - goto s_pad; - } - goto error; // unsupported if replicating the same string multiple times - case 3: - // skip '-' still buggy ... - goto again; + switch (cStrlenSet) { + // compute length with strlen + case 0: + for (ulIdx = 0; pcStr[ulIdx] != '\0'; ulIdx++) { + } + break; + + // use given length + case 1: + ulIdx = ulStrlen; + break; + + // printout prepad + case 2: + // if string is empty, then, ' ' padding + if (pcStr[0] == '\0') { + // pad with ulStrlen white spaces + do { + mcu_usb_prints(" ", 1); + } while (ulStrlen-- > 0); + + goto s_pad; + } + goto error; // unsupported if replicating the same string multiple + // times + case 3: + // skip '-' still buggy ... + goto again; } // // Write the string. // - switch(ulBase) { - default: - mcu_usb_prints(pcStr, ulIdx); - break; - case 16: { - unsigned char nibble1, nibble2; - unsigned int idx = 0; - for (ulCount = 0; ulCount < ulIdx; ulCount++) { - nibble1 = (pcStr[ulCount]>>4)&0xF; - nibble2 = pcStr[ulCount]&0xF; - switch(ulCap) { - case 0: - pcBuf[idx++] = g_pcHex[nibble1]; - pcBuf[idx++] = g_pcHex[nibble2]; - break; - case 1: - pcBuf[idx++] = g_pcHex_cap[nibble1]; - pcBuf[idx++] = g_pcHex_cap[nibble2]; - break; - } - if (idx + 1 >= sizeof(pcBuf)) { - mcu_usb_prints(pcBuf, idx); - idx = 0; - } - } - if (idx != 0) { - mcu_usb_prints(pcBuf, idx); + switch (ulBase) { + default: + mcu_usb_prints(pcStr, ulIdx); + break; + case 16: { + unsigned char nibble1, nibble2; + unsigned int idx = 0; + for (ulCount = 0; ulCount < ulIdx; ulCount++) { + nibble1 = (pcStr[ulCount] >> 4) & 0xF; + nibble2 = pcStr[ulCount] & 0xF; + switch (ulCap) { + case 0: + pcBuf[idx++] = g_pcHex[nibble1]; + pcBuf[idx++] = g_pcHex[nibble2]; + break; + case 1: + pcBuf[idx++] = g_pcHex_cap[nibble1]; + pcBuf[idx++] = g_pcHex_cap[nibble2]; + break; + } + if (idx + 1 >= sizeof(pcBuf)) { + mcu_usb_prints(pcBuf, idx); + idx = 0; + } + } + if (idx != 0) { + mcu_usb_prints(pcBuf, idx); + } + break; } - break; - } } -s_pad: + s_pad: // // Write any required padding spaces // - if(ulCount > ulIdx) - { + if (ulCount > ulIdx) { ulCount -= ulIdx; - while(ulCount--) - { + while (ulCount--) { mcu_usb_prints(" ", 1); } } @@ -373,8 +386,7 @@ void mcu_usb_printf(const char* format, ...) { // // Handle the %u command. // - case 'u': - { + case 'u': { // // Get the value from the varargs. // @@ -412,8 +424,7 @@ void mcu_usb_printf(const char* format, ...) { ulCap = 1; FALL_THROUGH; case 'x': - case 'p': - { + case 'p': { // // Get the value from the varargs. // @@ -439,20 +450,17 @@ void mcu_usb_printf(const char* format, ...) { // Determine the number of digits in the string version of // the value. // -convert: - for(ulIdx = 1; - (((ulIdx * ulBase) <= ulValue) && - (((ulIdx * ulBase) / ulBase) == ulIdx)); - ulIdx *= ulBase, ulCount--) - { + convert: + for (ulIdx = 1; + (((ulIdx * ulBase) <= ulValue) && (((ulIdx * ulBase) / ulBase) == ulIdx)); + ulIdx *= ulBase, ulCount--) { } // // If the value is negative, reduce the count of padding // characters needed. // - if(ulNeg) - { + if (ulNeg) { ulCount--; } @@ -460,8 +468,7 @@ void mcu_usb_printf(const char* format, ...) { // If the value is negative and the value is padded with // zeros, then place the minus sign before the padding. // - if(ulNeg && (cFill == '0')) - { + if (ulNeg && (cFill == '0')) { // // Place the minus sign in the output buffer. // @@ -478,10 +485,8 @@ void mcu_usb_printf(const char* format, ...) { // Provide additional padding at the beginning of the // string conversion if needed. // - if((ulCount > 1) && (ulCount < 16)) - { - for(ulCount--; ulCount; ulCount--) - { + if ((ulCount > 1) && (ulCount < 16)) { + for (ulCount--; ulCount; ulCount--) { pcBuf[ulPos++] = cFill; } } @@ -490,8 +495,7 @@ void mcu_usb_printf(const char* format, ...) { // If the value is negative, then place the minus sign // before the number. // - if(ulNeg) - { + if (ulNeg) { // // Place the minus sign in the output buffer. // @@ -501,13 +505,12 @@ void mcu_usb_printf(const char* format, ...) { // // Convert the value into a string. // - for(; ulIdx; ulIdx /= ulBase) - { + for (; ulIdx; ulIdx /= ulBase) { if (!ulCap) { - pcBuf[ulPos++] = g_pcHex[(ulValue / ulIdx) % ulBase]; + pcBuf[ulPos++] = g_pcHex[(ulValue / ulIdx) % ulBase]; } else { - pcBuf[ulPos++] = g_pcHex_cap[(ulValue / ulIdx) % ulBase]; + pcBuf[ulPos++] = g_pcHex_cap[(ulValue / ulIdx) % ulBase]; } } @@ -525,8 +528,7 @@ void mcu_usb_printf(const char* format, ...) { // // Handle the %% command. // - case '%': - { + case '%': { // // Simply write a single %. // @@ -538,12 +540,11 @@ void mcu_usb_printf(const char* format, ...) { break; } -error: + error: // // Handle all other commands. // - default: - { + default: { // // Indicate an error. // @@ -564,22 +565,22 @@ void mcu_usb_printf(const char* format, ...) { va_end(vaArgP); } -#endif // HAVE_PRINTF +#endif // HAVE_PRINTF #ifdef HAVE_SPRINTF -//unsigned int snprintf(unsigned char * str, unsigned int str_size, const char* format, ...) -int snprintf(char * str, size_t str_size, const char * format, ...) - { +// unsigned int snprintf(unsigned char * str, unsigned int str_size, const char* format, ...) +int snprintf(char *str, size_t str_size, const char *format, ...) +{ unsigned int ulIdx, ulValue, ulPos, ulCount, ulBase, ulNeg, ulStrlen, ulCap; - char *pcStr, pcBuf[16], cFill; - va_list vaArgP; - char cStrlenSet; + char *pcStr, pcBuf[16], cFill; + va_list vaArgP; + char cStrlenSet; // // Check the arguments. // - if(str == NULL ||str_size < 1) { - return 0; + if (str == NULL || str_size < 1) { + return 0; } // ensure terminating string with a \0 @@ -589,8 +590,8 @@ int snprintf(char * str, size_t str_size, const char * format, ...) // // Check if there is still space left for data in the buffer. // - if(str_size < 1) { - return 0; + if (str_size < 1) { + return 0; } // @@ -601,14 +602,11 @@ int snprintf(char * str, size_t str_size, const char * format, ...) // // Loop while there are more characters in the string. // - while(*format) - { + while (*format) { // // Find the first non-% character, or the end of the string. // - for(ulIdx = 0; (format[ulIdx] != '%') && (format[ulIdx] != '\0'); - ulIdx++) - { + for (ulIdx = 0; (format[ulIdx] != '%') && (format[ulIdx] != '\0'); ulIdx++) { } // @@ -616,7 +614,7 @@ int snprintf(char * str, size_t str_size, const char * format, ...) // ulIdx = MIN(ulIdx, str_size); memmove(str, format, ulIdx); - str+= ulIdx; + str += ulIdx; str_size -= ulIdx; if (str_size == 0) { va_end(vaArgP); @@ -631,8 +629,7 @@ int snprintf(char * str, size_t str_size, const char * format, ...) // // See if the next character is a %. // - if(*format == '%') - { + if (*format == '%') { // // Skip the %. // @@ -642,26 +639,24 @@ int snprintf(char * str, size_t str_size, const char * format, ...) // Set the digit count to zero, and the fill character to space // (i.e. to the defaults). // - ulCount = 0; - cFill = ' '; - ulStrlen = 0; + ulCount = 0; + cFill = ' '; + ulStrlen = 0; cStrlenSet = 0; - ulCap = 0; - ulBase = 10; + ulCap = 0; + ulBase = 10; // // It may be necessary to get back here to process more characters. // Goto's aren't pretty, but effective. I feel extremely dirty for // using not one but two of the beasts. // -again: + again: // // Determine how to handle the next character. // - switch(*format++) - { - + switch (*format++) { // // Handle the digit characters. // @@ -674,14 +669,12 @@ int snprintf(char * str, size_t str_size, const char * format, ...) case '6': case '7': case '8': - case '9': - { + case '9': { // // If this is a zero, and it is the first digit, then the // fill character is a zero instead of a space. // - if((format[-1] == '0') && (ulCount == 0)) - { + if ((format[-1] == '0') && (ulCount == 0)) { cFill = '0'; } @@ -700,8 +693,7 @@ int snprintf(char * str, size_t str_size, const char * format, ...) // // Handle the %c command. // - case 'c': - { + case 'c': { // // Get the value from the varargs. // @@ -727,8 +719,7 @@ int snprintf(char * str, size_t str_size, const char * format, ...) // // Handle the %d command. // - case 'd': - { + case 'd': { // // Get the value from the varargs. // @@ -743,20 +734,18 @@ int snprintf(char * str, size_t str_size, const char * format, ...) // If the value is negative, make it positive and indicate // that a minus sign is needed. // - if((long)ulValue < 0) - { + if ((long) ulValue < 0) { // // Make the value positive. // - ulValue = -(long)ulValue; + ulValue = -(long) ulValue; // // Indicate that the value is negative. // ulNeg = 1; } - else - { + else { // // Indicate that the value is positive so that a minus // sign isn't inserted. @@ -777,59 +766,56 @@ int snprintf(char * str, size_t str_size, const char * format, ...) // // Handle the %.*s command - // special %.*H or %.*h format to print a given length of hex digits (case: H UPPER, h lower) + // special %.*H or %.*h format to print a given length of hex digits (case: H UPPER, + // h lower) // - case '.': - { - // ensure next char is '*' and next one is 's'/'h'/'H' - if (format[0] == '*' && (format[1] == 's' || format[1] == 'H' || format[1] == 'h')) { + case '.': { + // ensure next char is '*' and next one is 's'/'h'/'H' + if (format[0] == '*' + && (format[1] == 's' || format[1] == 'H' || format[1] == 'h')) { + // skip '*' char + format++; - // skip '*' char - format++; + ulStrlen = va_arg(vaArgP, unsigned long); + cStrlenSet = 1; - ulStrlen = va_arg(vaArgP, unsigned long); - cStrlenSet = 1; - - // interpret next char (H/h/s) - goto again; - } + // interpret next char (H/h/s) + goto again; + } - // does not support %.2x for example - goto error; + // does not support %.2x for example + goto error; } - case '*': - { - if (*format == 's' ) { - - ulStrlen = va_arg(vaArgP, unsigned long); - cStrlenSet = 2; - goto again; - } + case '*': { + if (*format == 's') { + ulStrlen = va_arg(vaArgP, unsigned long); + cStrlenSet = 2; + goto again; + } - goto error; + goto error; } - case '-': // -XXs + case '-': // -XXs { - cStrlenSet = 0; - // read a number of space to post pad with ' ' the string to display - goto again; + cStrlenSet = 0; + // read a number of space to post pad with ' ' the string to display + goto again; } // // Handle the %s command. // %H and %h also case 'H': - ulCap = 1; // uppercase base 16 - ulBase = 16; - goto case_s; + ulCap = 1; // uppercase base 16 + ulBase = 16; + goto case_s; case 'h': - ulBase = 16; // lowercase base 16 - goto case_s; + ulBase = 16; // lowercase base 16 + goto case_s; case 's': - case_s: - { + case_s : { // // Get the string pointer from the varargs. // @@ -838,96 +824,94 @@ int snprintf(char * str, size_t str_size, const char * format, ...) // // Determine the length of the string. (if not specified using .*) // - switch(cStrlenSet) { - // compute length with strlen - case 0: - for(ulIdx = 0; pcStr[ulIdx] != '\0'; ulIdx++) - { - } - break; - - // use given length - case 1: - ulIdx = ulStrlen; - break; - - // printout prepad - case 2: - // if string is empty, then, ' ' padding - if (pcStr[0] == '\0') { - - // pad with ulStrlen white spaces - ulStrlen = MIN(ulStrlen, str_size); - memset(str, ' ', ulStrlen); - str+= ulStrlen; - str_size -= ulStrlen; - if (str_size == 0) { - va_end(vaArgP); - return 0; - } - - goto s_pad; - } - goto error; // unsupported if replicating the same string multiple times - case 3: - // skip '-' still buggy ... - goto again; + switch (cStrlenSet) { + // compute length with strlen + case 0: + for (ulIdx = 0; pcStr[ulIdx] != '\0'; ulIdx++) { + } + break; + + // use given length + case 1: + ulIdx = ulStrlen; + break; + + // printout prepad + case 2: + // if string is empty, then, ' ' padding + if (pcStr[0] == '\0') { + // pad with ulStrlen white spaces + ulStrlen = MIN(ulStrlen, str_size); + memset(str, ' ', ulStrlen); + str += ulStrlen; + str_size -= ulStrlen; + if (str_size == 0) { + va_end(vaArgP); + return 0; + } + + goto s_pad; + } + goto error; // unsupported if replicating the same string multiple + // times + case 3: + // skip '-' still buggy ... + goto again; } // // Write the string. // - switch(ulBase) { - default: - ulIdx = MIN(ulIdx, str_size); - memmove(str, pcStr, ulIdx); - str+= ulIdx; - str_size -= ulIdx; - if (str_size == 0) { - va_end(vaArgP); - return 0; + switch (ulBase) { + default: + ulIdx = MIN(ulIdx, str_size); + memmove(str, pcStr, ulIdx); + str += ulIdx; + str_size -= ulIdx; + if (str_size == 0) { + va_end(vaArgP); + return 0; + } + break; + case 16: { + unsigned char nibble1, nibble2; + for (ulCount = 0; ulCount < ulIdx; ulCount++) { + nibble1 = (pcStr[ulCount] >> 4) & 0xF; + nibble2 = pcStr[ulCount] & 0xF; + if (str_size < 2) { + va_end(vaArgP); + return 0; + } + switch (ulCap) { + case 0: + str[0] = g_pcHex[nibble1]; + str[1] = g_pcHex[nibble2]; + break; + case 1: + str[0] = g_pcHex_cap[nibble1]; + str[1] = g_pcHex_cap[nibble2]; + break; + } + str += 2; + str_size -= 2; + if (str_size == 0) { + va_end(vaArgP); + return 0; + } + } + break; } - break; - case 16: { - unsigned char nibble1, nibble2; - for (ulCount = 0; ulCount < ulIdx; ulCount++) { - nibble1 = (pcStr[ulCount]>>4)&0xF; - nibble2 = pcStr[ulCount]&0xF; - if (str_size < 2) { - va_end(vaArgP); - return 0; - } - switch(ulCap) { - case 0: - str[0] = g_pcHex[nibble1]; - str[1] = g_pcHex[nibble2]; - break; - case 1: - str[0] = g_pcHex_cap[nibble1]; - str[1] = g_pcHex_cap[nibble2]; - break; - } - str+= 2; - str_size -= 2; - if (str_size == 0) { - va_end(vaArgP); - return 0; - } - } - break; - } } -s_pad: + s_pad: // // Write any required padding spaces // - if(ulCount > ulIdx) - { + if (ulCount > ulIdx) { ulCount -= ulIdx; ulCount = MIN(ulCount, str_size); memset(str, ' ', ulCount); - str+= ulCount; + str += ulCount; str_size -= ulCount; if (str_size == 0) { va_end(vaArgP); @@ -944,8 +928,7 @@ int snprintf(char * str, size_t str_size, const char * format, ...) // // Handle the %u command. // - case 'u': - { + case 'u': { // // Get the value from the varargs. // @@ -972,7 +955,7 @@ int snprintf(char * str, size_t str_size, const char * format, ...) // goto convert; } -#endif // HAVE_SNPRINTF_FORMAT_U +#endif // HAVE_SNPRINTF_FORMAT_U // // Handle the %x and %X commands. Note that they are treated @@ -984,8 +967,7 @@ int snprintf(char * str, size_t str_size, const char * format, ...) ulCap = 1; FALL_THROUGH; case 'x': - case 'p': - { + case 'p': { // // Get the value from the varargs. // @@ -1011,20 +993,17 @@ int snprintf(char * str, size_t str_size, const char * format, ...) // Determine the number of digits in the string version of // the value. // -convert: - for(ulIdx = 1; - (((ulIdx * ulBase) <= ulValue) && - (((ulIdx * ulBase) / ulBase) == ulIdx)); - ulIdx *= ulBase, ulCount--) - { + convert: + for (ulIdx = 1; + (((ulIdx * ulBase) <= ulValue) && (((ulIdx * ulBase) / ulBase) == ulIdx)); + ulIdx *= ulBase, ulCount--) { } // // If the value is negative, reduce the count of padding // characters needed. // - if(ulNeg) - { + if (ulNeg) { ulCount--; } @@ -1032,8 +1011,7 @@ int snprintf(char * str, size_t str_size, const char * format, ...) // If the value is negative and the value is padded with // zeros, then place the minus sign before the padding. // - if(ulNeg && (cFill == '0')) - { + if (ulNeg && (cFill == '0')) { // // Place the minus sign in the output buffer. // @@ -1050,10 +1028,8 @@ int snprintf(char * str, size_t str_size, const char * format, ...) // Provide additional padding at the beginning of the // string conversion if needed. // - if((ulCount > 1) && (ulCount < 16)) - { - for(ulCount--; ulCount; ulCount--) - { + if ((ulCount > 1) && (ulCount < 16)) { + for (ulCount--; ulCount; ulCount--) { pcBuf[ulPos++] = cFill; } } @@ -1062,8 +1038,7 @@ int snprintf(char * str, size_t str_size, const char * format, ...) // If the value is negative, then place the minus sign // before the number. // - if(ulNeg) - { + if (ulNeg) { // // Place the minus sign in the output buffer. // @@ -1073,13 +1048,12 @@ int snprintf(char * str, size_t str_size, const char * format, ...) // // Convert the value into a string. // - for(; ulIdx; ulIdx /= ulBase) - { + for (; ulIdx; ulIdx /= ulBase) { if (!ulCap) { - pcBuf[ulPos++] = g_pcHex[(ulValue / ulIdx) % ulBase]; + pcBuf[ulPos++] = g_pcHex[(ulValue / ulIdx) % ulBase]; } else { - pcBuf[ulPos++] = g_pcHex_cap[(ulValue / ulIdx) % ulBase]; + pcBuf[ulPos++] = g_pcHex_cap[(ulValue / ulIdx) % ulBase]; } } @@ -1088,7 +1062,7 @@ int snprintf(char * str, size_t str_size, const char * format, ...) // ulPos = MIN(ulPos, str_size); memmove(str, pcBuf, ulPos); - str+= ulPos; + str += ulPos; str_size -= ulPos; if (str_size == 0) { va_end(vaArgP); @@ -1104,14 +1078,13 @@ int snprintf(char * str, size_t str_size, const char * format, ...) // // Handle the %% command. // - case '%': - { + case '%': { // // Simply write a single %. // str[0] = '%'; str++; - str_size --; + str_size--; if (str_size == 0) { va_end(vaArgP); return 0; @@ -1123,25 +1096,24 @@ int snprintf(char * str, size_t str_size, const char * format, ...) break; } -error: + error: // // Handle all other commands. // - default: - { + default: { #ifdef HAVE_SNPRINTF_DEBUG // // Indicate an error. // ulPos = MIN(strlen("ERROR"), str_size); memmove(str, "ERROR", ulPos); - str+= ulPos; + str += ulPos; str_size -= ulPos; if (str_size == 0) { va_end(vaArgP); return 0; } -#endif // HAVE_SNPRINTF_DEBUG +#endif // HAVE_SNPRINTF_DEBUG // // This command has been handled. @@ -1159,4 +1131,4 @@ int snprintf(char * str, size_t str_size, const char * format, ...) return 0; } -#endif // HAVE_SPRINTF +#endif // HAVE_SPRINTF diff --git a/src/pic.c b/src/pic.c index ec4938ad6..aee063083 100644 --- a/src/pic.c +++ b/src/pic.c @@ -1,19 +1,19 @@ #include "bolos_target.h" #include "os_pic.h" -#pragma GCC diagnostic push -#pragma GCC diagnostic ignored "-Wunused-parameter" -__attribute__((naked,no_instrument_function)) void *pic_internal(void *link_address) +#pragma GCC diagnostic push +#pragma GCC diagnostic ignored "-Wunused-parameter" +__attribute__((naked, no_instrument_function)) void *pic_internal(void *link_address) { - // compute the delta offset between LinkMemAddr & ExecMemAddr - __asm volatile ("mov r2, pc\n"); - __asm volatile ("ldr r1, =pic_internal\n"); - __asm volatile ("adds r1, r1, #3\n"); - __asm volatile ("subs r1, r1, r2\n"); + // compute the delta offset between LinkMemAddr & ExecMemAddr + __asm volatile("mov r2, pc\n"); + __asm volatile("ldr r1, =pic_internal\n"); + __asm volatile("adds r1, r1, #3\n"); + __asm volatile("subs r1, r1, r2\n"); - // adjust value of the given parameter - __asm volatile ("subs r0, r0, r1\n"); - __asm volatile ("bx lr\n"); + // adjust value of the given parameter + __asm volatile("subs r0, r0, r1\n"); + __asm volatile("bx lr\n"); } #pragma GCC diagnostic pop @@ -24,13 +24,14 @@ extern void _envram; #if defined(ST31) -void *pic(void *link_address) { - // check if in the LINKED TEXT zone - if (link_address >= &_nvram && link_address < &_envram) { - link_address = pic_internal(link_address); - } +void *pic(void *link_address) +{ + // check if in the LINKED TEXT zone + if (link_address >= &_nvram && link_address < &_envram) { + link_address = pic_internal(link_address); + } - return link_address; + return link_address; } #elif defined(ST33) || defined(ST33K1M5) @@ -38,26 +39,27 @@ void *pic(void *link_address) { extern void _bss; extern void _estack; -void *pic(void *link_address) { - void *n, *en; +void *pic(void *link_address) +{ + void *n, *en; - // check if in the LINKED TEXT zone - __asm volatile("ldr %0, =_nvram":"=r"(n)); - __asm volatile("ldr %0, =_envram":"=r"(en)); - if (link_address >= n && link_address <= en) { - link_address = pic_internal(link_address); - } + // check if in the LINKED TEXT zone + __asm volatile("ldr %0, =_nvram" : "=r"(n)); + __asm volatile("ldr %0, =_envram" : "=r"(en)); + if (link_address >= n && link_address <= en) { + link_address = pic_internal(link_address); + } - // check if in the LINKED RAM zone - __asm volatile("ldr %0, =_bss":"=r"(n)); - __asm volatile("ldr %0, =_estack":"=r"(en)); - if (link_address >= n && link_address <= en) { - __asm volatile("mov %0, r9":"=r"(en)); - // deref into the RAM therefore add the RAM offset from R9 - link_address = (char *)link_address - (char *)n + (char *)en; - } + // check if in the LINKED RAM zone + __asm volatile("ldr %0, =_bss" : "=r"(n)); + __asm volatile("ldr %0, =_estack" : "=r"(en)); + if (link_address >= n && link_address <= en) { + __asm volatile("mov %0, r9" : "=r"(en)); + // deref into the RAM therefore add the RAM offset from R9 + link_address = (char *) link_address - (char *) n + (char *) en; + } - return link_address; + return link_address; } #else diff --git a/src/syscalls.c b/src/syscalls.c index f9a83fbed..5762b7ba8 100644 --- a/src/syscalls.c +++ b/src/syscalls.c @@ -1,8 +1,8 @@ #define SYSCALL_STUB #if defined(HAVE_BOLOS) -# include "bolos_privileged_ux.h" -#endif // HAVE_BOLOS +#include "bolos_privileged_ux.h" +#endif // HAVE_BOLOS #include "bolos_target.h" #include "exceptions.h" @@ -16,13 +16,13 @@ #include "os_ux.h" #ifdef HAVE_SE_TOUCH #include "os_io.h" -#endif // HAVE_SE_TOUCH +#endif // HAVE_SE_TOUCH #include "ox_ec.h" #include "ox_bn.h" #include "syscalls.h" #if defined(HAVE_LANGUAGE_PACK) #include "ux.h" -#endif //defined(HAVE_LANGUAGE_PACK) +#endif // defined(HAVE_LANGUAGE_PACK) #ifdef HAVE_NBGL #include "nbgl_types.h" #include "nbgl_fonts.h" @@ -30,1896 +30,2239 @@ #endif #if defined(HAVE_VSS) #include "ox_vss.h" -#endif // HAVE_VSS +#endif // HAVE_VSS #include "os_seed.h" #include unsigned int SVC_Call(unsigned int syscall_id, void *parameters); -unsigned int SVC_cx_call(unsigned int syscall_id, unsigned int * parameters); +unsigned int SVC_cx_call(unsigned int syscall_id, unsigned int *parameters); -unsigned int get_api_level(void) { - unsigned int parameters[2]; - parameters[0] = 0; - parameters[1] = 0; - return SVC_Call(SYSCALL_get_api_level_ID, parameters); +unsigned int get_api_level(void) +{ + unsigned int parameters[2]; + parameters[0] = 0; + parameters[1] = 0; + return SVC_Call(SYSCALL_get_api_level_ID, parameters); } -void halt ( void ) { - unsigned int parameters[2]; - parameters[1] = 0; - SVC_Call(SYSCALL_halt_ID, parameters); - return; +void halt(void) +{ + unsigned int parameters[2]; + parameters[1] = 0; + SVC_Call(SYSCALL_halt_ID, parameters); + return; } #ifdef HAVE_NBGL void nbgl_frontDrawRect(nbgl_area_t *area) { - unsigned int parameters[1]; - parameters[0] = (unsigned int)area; - SVC_Call(SYSCALL_nbgl_front_draw_rect_ID, parameters); - return; + unsigned int parameters[1]; + parameters[0] = (unsigned int) area; + SVC_Call(SYSCALL_nbgl_front_draw_rect_ID, parameters); + return; } void nbgl_frontDrawHorizontalLine(nbgl_area_t *area, uint8_t mask, color_t lineColor) { - unsigned int parameters[3]; - parameters[0] = (unsigned int)area; - parameters[1] = (unsigned int)mask; - parameters[2] = (unsigned int)lineColor; - SVC_Call(SYSCALL_nbgl_front_draw_horizontal_line_ID, parameters); - return; + unsigned int parameters[3]; + parameters[0] = (unsigned int) area; + parameters[1] = (unsigned int) mask; + parameters[2] = (unsigned int) lineColor; + SVC_Call(SYSCALL_nbgl_front_draw_horizontal_line_ID, parameters); + return; +} + +void nbgl_frontDrawImage(nbgl_area_t *area, + uint8_t *buffer, + nbgl_transformation_t transformation, + nbgl_color_map_t colorMap) +{ + unsigned int parameters[4]; + parameters[0] = (unsigned int) area; + parameters[1] = (unsigned int) PIC(buffer); + parameters[2] = (unsigned int) transformation; + parameters[3] = (unsigned int) colorMap; + SVC_Call(SYSCALL_nbgl_front_draw_img_ID, parameters); + return; +} + +void nbgl_frontDrawImageRle(nbgl_area_t *area, + uint8_t *buffer, + uint32_t buffer_len, + color_t fore_color, + uint8_t nb_skipped_bytes) +{ + unsigned int parameters[5]; + parameters[0] = (unsigned int) area; + parameters[1] = (unsigned int) PIC(buffer); + parameters[2] = (unsigned int) buffer_len; + parameters[3] = (unsigned int) fore_color; + parameters[4] = (unsigned int) nb_skipped_bytes; + SVC_Call(SYSCALL_nbgl_front_draw_img_rle_ID, parameters); + return; +} + +void nbgl_frontDrawImageFile(nbgl_area_t *area, + uint8_t *buffer, + nbgl_color_map_t colorMap, + uint8_t *optional_uzlib_work_buffer) +{ + unsigned int parameters[4]; + parameters[0] = (unsigned int) area; + parameters[1] = (unsigned int) PIC(buffer); + parameters[2] = (unsigned int) colorMap; + parameters[3] = (unsigned int) optional_uzlib_work_buffer; + SVC_Call(SYSCALL_nbgl_front_draw_img_file_ID, parameters); + return; +} + +void nbgl_frontRefreshArea(nbgl_area_t *area, + nbgl_refresh_mode_t mode, + nbgl_post_refresh_t post_refresh) +{ + unsigned int parameters[3]; + parameters[0] = (unsigned int) area; + parameters[1] = (unsigned int) mode; + parameters[2] = (unsigned int) post_refresh; + SVC_Call(SYSCALL_nbgl_front_refresh_area_ID, parameters); + return; } -void nbgl_frontDrawImage(nbgl_area_t *area, uint8_t *buffer, nbgl_transformation_t transformation, nbgl_color_map_t colorMap) +void nbgl_sideDrawRect(nbgl_area_t *area) { - unsigned int parameters[4]; - parameters[0] = (unsigned int)area; - parameters[1] = (unsigned int)PIC(buffer); - parameters[2] = (unsigned int)transformation; - parameters[3] = (unsigned int)colorMap; - SVC_Call(SYSCALL_nbgl_front_draw_img_ID, parameters); - return; + unsigned int parameters[1]; + parameters[0] = (unsigned int) area; + SVC_Call(SYSCALL_nbgl_side_draw_rect_ID, parameters); + return; } -void nbgl_frontDrawImageRle(nbgl_area_t *area, uint8_t *buffer, uint32_t buffer_len, color_t fore_color, uint8_t nb_skipped_bytes) +void nbgl_sideDrawHorizontalLine(nbgl_area_t *area, uint8_t mask, color_t lineColor) { - unsigned int parameters[5]; - parameters[0] = (unsigned int)area; - parameters[1] = (unsigned int)PIC(buffer); - parameters[2] = (unsigned int)buffer_len; - parameters[3] = (unsigned int)fore_color; - parameters[4] = (unsigned int)nb_skipped_bytes; - SVC_Call(SYSCALL_nbgl_front_draw_img_rle_ID, parameters); - return; + unsigned int parameters[3]; + parameters[0] = (unsigned int) area; + parameters[1] = (unsigned int) mask; + parameters[2] = (unsigned int) lineColor; + SVC_Call(SYSCALL_nbgl_side_draw_horizontal_line_ID, parameters); + return; +} + +void nbgl_sideDrawImage(nbgl_area_t *area, + uint8_t *buffer, + nbgl_transformation_t transformation, + nbgl_color_map_t colorMap) +{ + unsigned int parameters[4]; + parameters[0] = (unsigned int) area; + parameters[1] = (unsigned int) buffer; + parameters[2] = (unsigned int) transformation; + parameters[3] = (unsigned int) colorMap; + SVC_Call(SYSCALL_nbgl_side_draw_img_ID, parameters); + return; } -void nbgl_frontDrawImageFile(nbgl_area_t *area, uint8_t *buffer, - nbgl_color_map_t colorMap, uint8_t *optional_uzlib_work_buffer) +void nbgl_sideRefreshArea(nbgl_area_t *area, nbgl_post_refresh_t post_refresh) { - unsigned int parameters[4]; - parameters[0] = (unsigned int)area; - parameters[1] = (unsigned int)PIC(buffer); - parameters[2] = (unsigned int)colorMap; - parameters[3] = (unsigned int)optional_uzlib_work_buffer; - SVC_Call(SYSCALL_nbgl_front_draw_img_file_ID, parameters); - return; + unsigned int parameters[2]; + parameters[0] = (unsigned int) area; + parameters[1] = (unsigned int) post_refresh; + SVC_Call(SYSCALL_nbgl_side_refresh_area_ID, parameters); + return; } -void nbgl_frontRefreshArea(nbgl_area_t *area, nbgl_refresh_mode_t mode, nbgl_post_refresh_t post_refresh) +const nbgl_font_t *nbgl_font_getFont(unsigned int fontId) { - unsigned int parameters[3]; - parameters[0] = (unsigned int)area; - parameters[1] = (unsigned int)mode; - parameters[2] = (unsigned int)post_refresh; - SVC_Call(SYSCALL_nbgl_front_refresh_area_ID, parameters); - return; + unsigned int parameters[1]; + parameters[0] = (unsigned int) fontId; + return (const nbgl_font_t *) SVC_Call(SYSCALL_nbgl_get_font_ID, parameters); } -void nbgl_sideDrawRect(nbgl_area_t *area) +unsigned int nbgl_screen_reinit(void) { - unsigned int parameters[1]; - parameters[0] = (unsigned int)area; - SVC_Call(SYSCALL_nbgl_side_draw_rect_ID, parameters); - return; + unsigned int parameters[1]; + parameters[0] = 0; + return SVC_Call(SYSCALL_nbgl_screen_reinit_ID, parameters); } -void nbgl_sideDrawHorizontalLine(nbgl_area_t *area, uint8_t mask, color_t lineColor) +#ifdef HAVE_DISPLAY_FAST_MODE +void nbgl_screen_update_temperature(uint8_t temp_degrees) { - unsigned int parameters[3]; - parameters[0] = (unsigned int)area; - parameters[1] = (unsigned int)mask; - parameters[2] = (unsigned int)lineColor; - SVC_Call(SYSCALL_nbgl_side_draw_horizontal_line_ID, parameters); - return; + unsigned int parameters[1]; + parameters[0] = (unsigned int) temp_degrees; + SVC_Call(SYSCALL_nbgl_screen_update_temperature_ID, parameters); + return; } +#endif // HAVE_DISPLAY_FAST_MODE -void nbgl_sideDrawImage(nbgl_area_t *area, uint8_t *buffer, nbgl_transformation_t transformation, nbgl_color_map_t colorMap) +#ifdef HAVE_CONFIGURABLE_DISPLAY_FAST_MODE +void nbgl_screen_config_fast_mode(uint8_t fast_mode_setting) { - unsigned int parameters[4]; - parameters[0] = (unsigned int)area; - parameters[1] = (unsigned int)buffer; - parameters[2] = (unsigned int)transformation; - parameters[3] = (unsigned int)colorMap; - SVC_Call(SYSCALL_nbgl_side_draw_img_ID, parameters); - return; + unsigned int parameters[1]; + parameters[0] = (unsigned int) fast_mode_setting; + SVC_Call(SYSCALL_nbgl_screen_config_fast_mode_ID, parameters); } +#endif // HAVE_CONFIGURABLE_DISPLAY_FAST_MODE -void nbgl_sideRefreshArea(nbgl_area_t *area, nbgl_post_refresh_t post_refresh) +#endif + +void nvm_write(void *dst_adr, void *src_adr, unsigned int src_len) { - unsigned int parameters[2]; - parameters[0] = (unsigned int)area; - parameters[1] = (unsigned int)post_refresh; - SVC_Call(SYSCALL_nbgl_side_refresh_area_ID, parameters); - return; + unsigned int parameters[3]; + parameters[0] = (unsigned int) dst_adr; + parameters[1] = (unsigned int) src_adr; + parameters[2] = (unsigned int) src_len; + SVC_Call(SYSCALL_nvm_write_ID, parameters); + return; } -const nbgl_font_t* nbgl_font_getFont(unsigned int fontId) +void nvm_erase(void *dst_adr, unsigned int len) { - unsigned int parameters[1]; - parameters[0] = (unsigned int)fontId; - return (const nbgl_font_t*)SVC_Call(SYSCALL_nbgl_get_font_ID, parameters); + unsigned int parameters[2]; + parameters[0] = (unsigned int) dst_adr; + parameters[1] = (unsigned int) len; + SVC_Call(SYSCALL_nvm_erase_ID, parameters); + return; } -unsigned int nbgl_screen_reinit(void) +cx_err_t cx_aes_set_key_hw(const cx_aes_key_t *keys, uint32_t mode) { - unsigned int parameters[1]; - parameters[0] = 0; - return SVC_Call(SYSCALL_nbgl_screen_reinit_ID, parameters); + unsigned int parameters[2]; + parameters[0] = (unsigned int) keys; + parameters[1] = (unsigned int) mode; + return SVC_cx_call(SYSCALL_cx_aes_set_key_hw_ID, parameters); } -#ifdef HAVE_DISPLAY_FAST_MODE -void nbgl_screen_update_temperature(uint8_t temp_degrees) +void cx_aes_reset_hw(void) { - unsigned int parameters[1]; - parameters[0] = (unsigned int) temp_degrees; - SVC_Call(SYSCALL_nbgl_screen_update_temperature_ID, parameters); - return; + unsigned int parameters[2]; + parameters[1] = 0; + SVC_cx_call(SYSCALL_cx_aes_reset_hw_ID, parameters); } -#endif // HAVE_DISPLAY_FAST_MODE -#ifdef HAVE_CONFIGURABLE_DISPLAY_FAST_MODE -void nbgl_screen_config_fast_mode(uint8_t fast_mode_setting) +cx_err_t cx_aes_block_hw(const unsigned char *inblock, unsigned char *outblock) { - unsigned int parameters[1]; - parameters[0] = (unsigned int) fast_mode_setting; - SVC_Call(SYSCALL_nbgl_screen_config_fast_mode_ID, parameters); + unsigned int parameters[2]; + parameters[0] = (unsigned int) inblock; + parameters[1] = (unsigned int) outblock; + return SVC_cx_call(SYSCALL_cx_aes_block_hw_ID, parameters); } -#endif // HAVE_CONFIGURABLE_DISPLAY_FAST_MODE -#endif +cx_err_t cx_bn_lock(size_t word_nbytes, uint32_t flags) +{ + unsigned int parameters[2]; + parameters[0] = (unsigned int) word_nbytes; + parameters[1] = (unsigned int) flags; + return SVC_cx_call(SYSCALL_cx_bn_lock_ID, parameters); +} -void nvm_write ( void * dst_adr, void * src_adr, unsigned int src_len ) { - unsigned int parameters[3]; - parameters[0] = (unsigned int)dst_adr; - parameters[1] = (unsigned int)src_adr; - parameters[2] = (unsigned int)src_len; - SVC_Call(SYSCALL_nvm_write_ID, parameters); - return; +uint32_t cx_bn_unlock(void) +{ + unsigned int parameters[2]; + parameters[1] = 0; + return (uint32_t) SVC_cx_call(SYSCALL_cx_bn_unlock_ID, parameters); } -void nvm_erase ( void * dst_adr, unsigned int len ) { - unsigned int parameters[2]; - parameters[0] = (unsigned int)dst_adr; - parameters[1] = (unsigned int)len; - SVC_Call(SYSCALL_nvm_erase_ID, parameters); - return; +_Bool cx_bn_is_locked(void) +{ + unsigned int parameters[2]; + parameters[1] = 0; + return (_Bool) SVC_cx_call(SYSCALL_cx_bn_is_locked_ID, parameters); } -cx_err_t cx_aes_set_key_hw ( const cx_aes_key_t * keys, uint32_t mode ) { - unsigned int parameters[2]; - parameters[0] = (unsigned int)keys; - parameters[1] = (unsigned int)mode; - return SVC_cx_call(SYSCALL_cx_aes_set_key_hw_ID, parameters); +cx_err_t cx_bn_alloc(cx_bn_t *x, size_t nbytes) +{ + unsigned int parameters[2]; + parameters[0] = (unsigned int) x; + parameters[1] = (unsigned int) nbytes; + return SVC_cx_call(SYSCALL_cx_bn_alloc_ID, parameters); } -void cx_aes_reset_hw ( void ) { - unsigned int parameters[2]; - parameters[1] = 0; - SVC_cx_call(SYSCALL_cx_aes_reset_hw_ID, parameters); +cx_err_t cx_bn_alloc_init(cx_bn_t *x, size_t nbytes, const uint8_t *value, size_t value_nbytes) +{ + unsigned int parameters[4]; + parameters[0] = (unsigned int) x; + parameters[1] = (unsigned int) nbytes; + parameters[2] = (unsigned int) value; + parameters[3] = (unsigned int) value_nbytes; + return SVC_cx_call(SYSCALL_cx_bn_alloc_init_ID, parameters); } -cx_err_t cx_aes_block_hw ( const unsigned char * inblock, unsigned char * outblock ) { - unsigned int parameters[2]; - parameters[0] = (unsigned int)inblock; - parameters[1] = (unsigned int)outblock; - return SVC_cx_call(SYSCALL_cx_aes_block_hw_ID, parameters); +cx_err_t cx_bn_destroy(cx_bn_t *x) +{ + unsigned int parameters[2]; + parameters[0] = (unsigned int) x; + parameters[1] = 0; + return SVC_cx_call(SYSCALL_cx_bn_destroy_ID, parameters); } -cx_err_t cx_bn_lock ( size_t word_nbytes, uint32_t flags ) { - unsigned int parameters[2]; - parameters[0] = (unsigned int)word_nbytes; - parameters[1] = (unsigned int)flags; - return SVC_cx_call(SYSCALL_cx_bn_lock_ID, parameters); +cx_err_t cx_bn_nbytes(const cx_bn_t x, size_t *nbytes) +{ + unsigned int parameters[2]; + parameters[0] = (unsigned int) x; + parameters[1] = (unsigned int) nbytes; + return SVC_cx_call(SYSCALL_cx_bn_nbytes_ID, parameters); } -uint32_t cx_bn_unlock ( void ) { - unsigned int parameters[2]; - parameters[1] = 0; - return (uint32_t) SVC_cx_call(SYSCALL_cx_bn_unlock_ID, parameters); +cx_err_t cx_bn_init(cx_bn_t x, const uint8_t *value, size_t value_nbytes) +{ + unsigned int parameters[3]; + parameters[0] = (unsigned int) x; + parameters[1] = (unsigned int) value; + parameters[2] = (unsigned int) value_nbytes; + return SVC_cx_call(SYSCALL_cx_bn_init_ID, parameters); } -_Bool cx_bn_is_locked ( void ) { - unsigned int parameters[2]; - parameters[1] = 0; - return (_Bool) SVC_cx_call(SYSCALL_cx_bn_is_locked_ID, parameters); +cx_err_t cx_bn_rand(cx_bn_t x) +{ + unsigned int parameters[2]; + parameters[0] = (unsigned int) x; + parameters[1] = 0; + return SVC_cx_call(SYSCALL_cx_bn_rand_ID, parameters); } -cx_err_t cx_bn_alloc ( cx_bn_t * x, size_t nbytes ) { - unsigned int parameters[2]; - parameters[0] = (unsigned int)x; - parameters[1] = (unsigned int)nbytes; - return SVC_cx_call(SYSCALL_cx_bn_alloc_ID, parameters); +cx_err_t cx_bn_copy(cx_bn_t a, const cx_bn_t b) +{ + unsigned int parameters[2]; + parameters[0] = (unsigned int) a; + parameters[1] = (unsigned int) b; + return SVC_cx_call(SYSCALL_cx_bn_copy_ID, parameters); } -cx_err_t cx_bn_alloc_init ( cx_bn_t * x, size_t nbytes, const uint8_t * value, size_t value_nbytes ) { - unsigned int parameters[4]; - parameters[0] = (unsigned int)x; - parameters[1] = (unsigned int)nbytes; - parameters[2] = (unsigned int)value; - parameters[3] = (unsigned int)value_nbytes; - return SVC_cx_call(SYSCALL_cx_bn_alloc_init_ID, parameters); +cx_err_t cx_bn_set_u32(cx_bn_t x, uint32_t n) +{ + unsigned int parameters[2]; + parameters[0] = (unsigned int) x; + parameters[1] = (unsigned int) n; + return SVC_cx_call(SYSCALL_cx_bn_set_u32_ID, parameters); } -cx_err_t cx_bn_destroy ( cx_bn_t * x ) { - unsigned int parameters[2]; - parameters[0] = (unsigned int)x; - parameters[1] = 0; - return SVC_cx_call(SYSCALL_cx_bn_destroy_ID, parameters); +cx_err_t cx_bn_get_u32(const cx_bn_t x, uint32_t *n) +{ + unsigned int parameters[3]; + parameters[0] = (unsigned int) x; + parameters[1] = (unsigned int) n; + parameters[2] = 0; + return SVC_cx_call(SYSCALL_cx_bn_get_u32_ID, parameters); } -cx_err_t cx_bn_nbytes ( const cx_bn_t x, size_t *nbytes ) { - unsigned int parameters[2]; - parameters[0] = (unsigned int)x; - parameters[1] = (unsigned int)nbytes; - return SVC_cx_call(SYSCALL_cx_bn_nbytes_ID, parameters); +cx_err_t cx_bn_export(const cx_bn_t x, uint8_t *bytes, size_t nbytes) +{ + unsigned int parameters[3]; + parameters[0] = (unsigned int) x; + parameters[1] = (unsigned int) bytes; + parameters[2] = (unsigned int) nbytes; + return SVC_cx_call(SYSCALL_cx_bn_export_ID, parameters); } -cx_err_t cx_bn_init ( cx_bn_t x, const uint8_t * value, size_t value_nbytes ) { - unsigned int parameters[3]; - parameters[0] = (unsigned int)x; - parameters[1] = (unsigned int)value; - parameters[2] = (unsigned int)value_nbytes; - return SVC_cx_call(SYSCALL_cx_bn_init_ID, parameters); +cx_err_t cx_bn_cmp(const cx_bn_t a, const cx_bn_t b, int *diff) +{ + unsigned int parameters[3]; + parameters[0] = (unsigned int) a; + parameters[1] = (unsigned int) b; + parameters[2] = (unsigned int) diff; + return SVC_cx_call(SYSCALL_cx_bn_cmp_ID, parameters); } -cx_err_t cx_bn_rand ( cx_bn_t x ) { - unsigned int parameters[2]; - parameters[0] = (unsigned int)x; - parameters[1] = 0; - return SVC_cx_call(SYSCALL_cx_bn_rand_ID, parameters); +cx_err_t cx_bn_cmp_u32(const cx_bn_t a, uint32_t b, int *diff) +{ + unsigned int parameters[3]; + parameters[0] = (unsigned int) a; + parameters[1] = (unsigned int) b; + parameters[2] = (unsigned int) diff; + return SVC_cx_call(SYSCALL_cx_bn_cmp_u32_ID, parameters); } -cx_err_t cx_bn_copy ( cx_bn_t a, const cx_bn_t b ) { - unsigned int parameters[2]; - parameters[0] = (unsigned int)a; - parameters[1] = (unsigned int)b; - return SVC_cx_call(SYSCALL_cx_bn_copy_ID, parameters); +cx_err_t cx_bn_is_odd(const cx_bn_t n, bool *odd) +{ + unsigned int parameters[2]; + parameters[0] = (unsigned int) n; + parameters[1] = (unsigned int) odd; + return SVC_cx_call(SYSCALL_cx_bn_is_odd_ID, parameters); } -cx_err_t cx_bn_set_u32 ( cx_bn_t x, uint32_t n ) { - unsigned int parameters[2]; - parameters[0] = (unsigned int)x; - parameters[1] = (unsigned int)n; - return SVC_cx_call(SYSCALL_cx_bn_set_u32_ID, parameters); +cx_err_t cx_bn_xor(cx_bn_t r, const cx_bn_t a, const cx_bn_t b) +{ + unsigned int parameters[3]; + parameters[0] = (unsigned int) r; + parameters[1] = (unsigned int) a; + parameters[2] = (unsigned int) b; + return SVC_cx_call(SYSCALL_cx_bn_xor_ID, parameters); } -cx_err_t cx_bn_get_u32(const cx_bn_t x, uint32_t *n) { - unsigned int parameters[3]; - parameters[0] = (unsigned int)x; - parameters[1] = (unsigned int)n; - parameters[2] = 0; - return SVC_cx_call(SYSCALL_cx_bn_get_u32_ID, parameters); +cx_err_t cx_bn_or(cx_bn_t r, const cx_bn_t a, const cx_bn_t b) +{ + unsigned int parameters[3]; + parameters[0] = (unsigned int) r; + parameters[1] = (unsigned int) a; + parameters[2] = (unsigned int) b; + return SVC_cx_call(SYSCALL_cx_bn_or_ID, parameters); } -cx_err_t cx_bn_export ( const cx_bn_t x, uint8_t * bytes, size_t nbytes ) { - unsigned int parameters[3]; - parameters[0] = (unsigned int)x; - parameters[1] = (unsigned int)bytes; - parameters[2] = (unsigned int)nbytes; - return SVC_cx_call(SYSCALL_cx_bn_export_ID, parameters); +cx_err_t cx_bn_and(cx_bn_t r, const cx_bn_t a, const cx_bn_t b) +{ + unsigned int parameters[3]; + parameters[0] = (unsigned int) r; + parameters[1] = (unsigned int) a; + parameters[2] = (unsigned int) b; + return SVC_cx_call(SYSCALL_cx_bn_and_ID, parameters); } -cx_err_t cx_bn_cmp ( const cx_bn_t a, const cx_bn_t b, int *diff ) { - unsigned int parameters[3]; - parameters[0] = (unsigned int)a; - parameters[1] = (unsigned int)b; - parameters[2] = (unsigned int)diff; - return SVC_cx_call(SYSCALL_cx_bn_cmp_ID, parameters); +cx_err_t cx_bn_tst_bit(const cx_bn_t x, uint32_t pos, bool *set) +{ + unsigned int parameters[3]; + parameters[0] = (unsigned int) x; + parameters[1] = (unsigned int) pos; + parameters[2] = (unsigned int) set; + return SVC_cx_call(SYSCALL_cx_bn_tst_bit_ID, parameters); } -cx_err_t cx_bn_cmp_u32 ( const cx_bn_t a, uint32_t b, int *diff ) { - unsigned int parameters[3]; - parameters[0] = (unsigned int)a; - parameters[1] = (unsigned int)b; - parameters[2] = (unsigned int)diff; - return SVC_cx_call(SYSCALL_cx_bn_cmp_u32_ID, parameters); +cx_err_t cx_bn_set_bit(cx_bn_t x, uint32_t pos) +{ + unsigned int parameters[2]; + parameters[0] = (unsigned int) x; + parameters[1] = (unsigned int) pos; + return SVC_cx_call(SYSCALL_cx_bn_set_bit_ID, parameters); } -cx_err_t cx_bn_is_odd ( const cx_bn_t n, bool *odd ) { - unsigned int parameters[2]; - parameters[0] = (unsigned int)n; - parameters[1] = (unsigned int)odd; - return SVC_cx_call(SYSCALL_cx_bn_is_odd_ID, parameters); +cx_err_t cx_bn_clr_bit(cx_bn_t x, uint32_t pos) +{ + unsigned int parameters[2]; + parameters[0] = (unsigned int) x; + parameters[1] = (unsigned int) pos; + return SVC_cx_call(SYSCALL_cx_bn_clr_bit_ID, parameters); } -cx_err_t cx_bn_xor ( cx_bn_t r, const cx_bn_t a, const cx_bn_t b ) { - unsigned int parameters[3]; - parameters[0] = (unsigned int)r; - parameters[1] = (unsigned int)a; - parameters[2] = (unsigned int)b; - return SVC_cx_call(SYSCALL_cx_bn_xor_ID, parameters); +cx_err_t cx_bn_shr(cx_bn_t x, uint32_t n) +{ + unsigned int parameters[2]; + parameters[0] = (unsigned int) x; + parameters[1] = (unsigned int) n; + return SVC_cx_call(SYSCALL_cx_bn_shr_ID, parameters); } -cx_err_t cx_bn_or ( cx_bn_t r, const cx_bn_t a, const cx_bn_t b ) { - unsigned int parameters[3]; - parameters[0] = (unsigned int)r; - parameters[1] = (unsigned int)a; - parameters[2] = (unsigned int)b; - return SVC_cx_call(SYSCALL_cx_bn_or_ID, parameters); +cx_err_t cx_bn_shl(cx_bn_t x, uint32_t n) +{ + unsigned int parameters[2]; + parameters[0] = (unsigned int) x; + parameters[1] = (unsigned int) n; + return SVC_cx_call(SYSCALL_cx_bn_shl_ID, parameters); } -cx_err_t cx_bn_and ( cx_bn_t r, const cx_bn_t a, const cx_bn_t b ) { - unsigned int parameters[3]; - parameters[0] = (unsigned int)r; - parameters[1] = (unsigned int)a; - parameters[2] = (unsigned int)b; - return SVC_cx_call(SYSCALL_cx_bn_and_ID, parameters); +cx_err_t cx_bn_cnt_bits(cx_bn_t n, uint32_t *nbits) +{ + unsigned int parameters[2]; + parameters[0] = (unsigned int) n; + parameters[1] = (unsigned int) nbits; + return SVC_cx_call(SYSCALL_cx_bn_cnt_bits_ID, parameters); } -cx_err_t cx_bn_tst_bit ( const cx_bn_t x, uint32_t pos, bool *set ) { - unsigned int parameters[3]; - parameters[0] = (unsigned int)x; - parameters[1] = (unsigned int)pos; - parameters[2] = (unsigned int)set; - return SVC_cx_call(SYSCALL_cx_bn_tst_bit_ID, parameters); +cx_err_t cx_bn_add(cx_bn_t r, const cx_bn_t a, const cx_bn_t b) +{ + unsigned int parameters[3]; + parameters[0] = (unsigned int) r; + parameters[1] = (unsigned int) a; + parameters[2] = (unsigned int) b; + return SVC_cx_call(SYSCALL_cx_bn_add_ID, parameters); } -cx_err_t cx_bn_set_bit ( cx_bn_t x, uint32_t pos ) { - unsigned int parameters[2]; - parameters[0] = (unsigned int)x; - parameters[1] = (unsigned int)pos; - return SVC_cx_call(SYSCALL_cx_bn_set_bit_ID, parameters); +cx_err_t cx_bn_sub(cx_bn_t r, const cx_bn_t a, const cx_bn_t b) +{ + unsigned int parameters[3]; + parameters[0] = (unsigned int) r; + parameters[1] = (unsigned int) a; + parameters[2] = (unsigned int) b; + return SVC_cx_call(SYSCALL_cx_bn_sub_ID, parameters); } -cx_err_t cx_bn_clr_bit ( cx_bn_t x, uint32_t pos ) { - unsigned int parameters[2]; - parameters[0] = (unsigned int)x; - parameters[1] = (unsigned int)pos; - return SVC_cx_call(SYSCALL_cx_bn_clr_bit_ID, parameters); +cx_err_t cx_bn_mul(cx_bn_t r, const cx_bn_t a, const cx_bn_t b) +{ + unsigned int parameters[3]; + parameters[0] = (unsigned int) r; + parameters[1] = (unsigned int) a; + parameters[2] = (unsigned int) b; + return SVC_cx_call(SYSCALL_cx_bn_mul_ID, parameters); } -cx_err_t cx_bn_shr ( cx_bn_t x, uint32_t n ) { - unsigned int parameters[2]; - parameters[0] = (unsigned int)x; - parameters[1] = (unsigned int)n; - return SVC_cx_call(SYSCALL_cx_bn_shr_ID, parameters); +cx_err_t cx_bn_mod_add(cx_bn_t r, const cx_bn_t a, const cx_bn_t b, const cx_bn_t n) +{ + unsigned int parameters[4]; + parameters[0] = (unsigned int) r; + parameters[1] = (unsigned int) a; + parameters[2] = (unsigned int) b; + parameters[3] = (unsigned int) n; + return SVC_cx_call(SYSCALL_cx_bn_mod_add_ID, parameters); } -cx_err_t cx_bn_shl ( cx_bn_t x, uint32_t n ) { - unsigned int parameters[2]; - parameters[0] = (unsigned int)x; - parameters[1] = (unsigned int)n; - return SVC_cx_call(SYSCALL_cx_bn_shl_ID, parameters); +cx_err_t cx_bn_mod_sub(cx_bn_t r, const cx_bn_t a, const cx_bn_t b, const cx_bn_t n) +{ + unsigned int parameters[4]; + parameters[0] = (unsigned int) r; + parameters[1] = (unsigned int) a; + parameters[2] = (unsigned int) b; + parameters[3] = (unsigned int) n; + return SVC_cx_call(SYSCALL_cx_bn_mod_sub_ID, parameters); } -cx_err_t cx_bn_cnt_bits ( cx_bn_t n, uint32_t *nbits ) { - unsigned int parameters[2]; - parameters[0] = (unsigned int)n; - parameters[1] = (unsigned int)nbits; - return SVC_cx_call(SYSCALL_cx_bn_cnt_bits_ID, parameters); +cx_err_t cx_bn_mod_mul(cx_bn_t r, const cx_bn_t a, const cx_bn_t b, const cx_bn_t n) +{ + unsigned int parameters[4]; + parameters[0] = (unsigned int) r; + parameters[1] = (unsigned int) a; + parameters[2] = (unsigned int) b; + parameters[3] = (unsigned int) n; + return SVC_cx_call(SYSCALL_cx_bn_mod_mul_ID, parameters); } -cx_err_t cx_bn_add ( cx_bn_t r, const cx_bn_t a, const cx_bn_t b ) { - unsigned int parameters[3]; - parameters[0] = (unsigned int)r; - parameters[1] = (unsigned int)a; - parameters[2] = (unsigned int)b; - return SVC_cx_call(SYSCALL_cx_bn_add_ID, parameters); +cx_err_t cx_bn_reduce(cx_bn_t r, const cx_bn_t d, const cx_bn_t n) +{ + unsigned int parameters[3]; + parameters[0] = (unsigned int) r; + parameters[1] = (unsigned int) d; + parameters[2] = (unsigned int) n; + return SVC_cx_call(SYSCALL_cx_bn_reduce_ID, parameters); } -cx_err_t cx_bn_sub ( cx_bn_t r, const cx_bn_t a, const cx_bn_t b ) { - unsigned int parameters[3]; - parameters[0] = (unsigned int)r; - parameters[1] = (unsigned int)a; - parameters[2] = (unsigned int)b; - return SVC_cx_call(SYSCALL_cx_bn_sub_ID, parameters); +cx_err_t cx_bn_mod_sqrt(cx_bn_t bn_r, const cx_bn_t bn_a, const cx_bn_t bn_n, uint32_t sign) +{ + unsigned int parameters[4]; + parameters[0] = (unsigned int) bn_r; + parameters[1] = (unsigned int) bn_a; + parameters[2] = (unsigned int) bn_n; + parameters[3] = (unsigned int) sign; + return SVC_cx_call(SYSCALL_cx_bn_mod_sqrt_ID, parameters); } -cx_err_t cx_bn_mul ( cx_bn_t r, const cx_bn_t a, const cx_bn_t b ) { - unsigned int parameters[3]; - parameters[0] = (unsigned int)r; - parameters[1] = (unsigned int)a; - parameters[2] = (unsigned int)b; - return SVC_cx_call(SYSCALL_cx_bn_mul_ID, parameters); +cx_err_t cx_bn_mod_pow_bn(cx_bn_t r, const cx_bn_t a, const cx_bn_t e, const cx_bn_t n) +{ + unsigned int parameters[4]; + parameters[0] = (unsigned int) r; + parameters[1] = (unsigned int) a; + parameters[2] = (unsigned int) e; + parameters[3] = (unsigned int) n; + return SVC_cx_call(SYSCALL_cx_bn_mod_pow_bn_ID, parameters); +} + +cx_err_t cx_bn_mod_pow(cx_bn_t r, + const cx_bn_t a, + const uint8_t *e, + uint32_t e_len, + const cx_bn_t n) +{ + unsigned int parameters[5]; + parameters[0] = (unsigned int) r; + parameters[1] = (unsigned int) a; + parameters[2] = (unsigned int) e; + parameters[3] = (unsigned int) e_len; + parameters[4] = (unsigned int) n; + return SVC_cx_call(SYSCALL_cx_bn_mod_pow_ID, parameters); +} + +cx_err_t cx_bn_mod_pow2(cx_bn_t r, + const cx_bn_t a, + const uint8_t *e, + uint32_t e_len, + const cx_bn_t n) +{ + unsigned int parameters[5]; + parameters[0] = (unsigned int) r; + parameters[1] = (unsigned int) a; + parameters[2] = (unsigned int) e; + parameters[3] = (unsigned int) e_len; + parameters[4] = (unsigned int) n; + return SVC_cx_call(SYSCALL_cx_bn_mod_pow2_ID, parameters); } -cx_err_t cx_bn_mod_add ( cx_bn_t r, const cx_bn_t a, const cx_bn_t b, const cx_bn_t n ) { - unsigned int parameters[4]; - parameters[0] = (unsigned int)r; - parameters[1] = (unsigned int)a; - parameters[2] = (unsigned int)b; - parameters[3] = (unsigned int)n; - return SVC_cx_call(SYSCALL_cx_bn_mod_add_ID, parameters); +cx_err_t cx_bn_mod_invert_nprime(cx_bn_t r, const cx_bn_t a, const cx_bn_t n) +{ + unsigned int parameters[3]; + parameters[0] = (unsigned int) r; + parameters[1] = (unsigned int) a; + parameters[2] = (unsigned int) n; + return SVC_cx_call(SYSCALL_cx_bn_mod_invert_nprime_ID, parameters); } -cx_err_t cx_bn_mod_sub ( cx_bn_t r, const cx_bn_t a, const cx_bn_t b, const cx_bn_t n ) { - unsigned int parameters[4]; - parameters[0] = (unsigned int)r; - parameters[1] = (unsigned int)a; - parameters[2] = (unsigned int)b; - parameters[3] = (unsigned int)n; - return SVC_cx_call(SYSCALL_cx_bn_mod_sub_ID, parameters); -} - -cx_err_t cx_bn_mod_mul ( cx_bn_t r, const cx_bn_t a, const cx_bn_t b, const cx_bn_t n ) { - unsigned int parameters[4]; - parameters[0] = (unsigned int)r; - parameters[1] = (unsigned int)a; - parameters[2] = (unsigned int)b; - parameters[3] = (unsigned int)n; - return SVC_cx_call(SYSCALL_cx_bn_mod_mul_ID, parameters); -} +cx_err_t cx_bn_mod_u32_invert(cx_bn_t r, uint32_t a, cx_bn_t n) +{ + unsigned int parameters[3]; + parameters[0] = (unsigned int) r; + parameters[1] = (unsigned int) a; + parameters[2] = (unsigned int) n; + return SVC_cx_call(SYSCALL_cx_bn_mod_u32_invert_ID, parameters); +} -cx_err_t cx_bn_reduce ( cx_bn_t r, const cx_bn_t d, const cx_bn_t n ) { - unsigned int parameters[3]; - parameters[0] = (unsigned int)r; - parameters[1] = (unsigned int)d; - parameters[2] = (unsigned int)n; - return SVC_cx_call(SYSCALL_cx_bn_reduce_ID, parameters); +cx_err_t cx_bn_is_prime(const cx_bn_t n, bool *prime) +{ + unsigned int parameters[2]; + parameters[0] = (unsigned int) n; + parameters[1] = (unsigned int) prime; + return SVC_cx_call(SYSCALL_cx_bn_is_prime_ID, parameters); } -cx_err_t cx_bn_mod_sqrt ( cx_bn_t bn_r, const cx_bn_t bn_a, const cx_bn_t bn_n, uint32_t sign ) { - unsigned int parameters[4]; - parameters[0] = (unsigned int)bn_r; - parameters[1] = (unsigned int)bn_a; - parameters[2] = (unsigned int)bn_n; - parameters[3] = (unsigned int)sign; - return SVC_cx_call(SYSCALL_cx_bn_mod_sqrt_ID, parameters); +cx_err_t cx_bn_next_prime(cx_bn_t n) +{ + unsigned int parameters[2]; + parameters[0] = (unsigned int) n; + parameters[1] = 0; + return SVC_cx_call(SYSCALL_cx_bn_next_prime_ID, parameters); } -cx_err_t cx_bn_mod_pow_bn ( cx_bn_t r, const cx_bn_t a, const cx_bn_t e, const cx_bn_t n ) { - unsigned int parameters[4]; - parameters[0] = (unsigned int)r; - parameters[1] = (unsigned int)a; - parameters[2] = (unsigned int)e; - parameters[3] = (unsigned int)n; - return SVC_cx_call(SYSCALL_cx_bn_mod_pow_bn_ID, parameters); +cx_err_t cx_bn_rng(cx_bn_t r, const cx_bn_t n) +{ + unsigned int parameters[2]; + parameters[0] = (unsigned int) r; + parameters[1] = (unsigned int) n; + return SVC_cx_call(SYSCALL_cx_bn_rng_ID, parameters); } -cx_err_t cx_bn_mod_pow ( cx_bn_t r, const cx_bn_t a, const uint8_t * e, uint32_t e_len, const cx_bn_t n ) { - unsigned int parameters[5]; - parameters[0] = (unsigned int)r; - parameters[1] = (unsigned int)a; - parameters[2] = (unsigned int)e; - parameters[3] = (unsigned int)e_len; - parameters[4] = (unsigned int)n; - return SVC_cx_call(SYSCALL_cx_bn_mod_pow_ID, parameters); -} - -cx_err_t cx_bn_mod_pow2 ( cx_bn_t r, const cx_bn_t a, const uint8_t * e, uint32_t e_len, const cx_bn_t n ) { - unsigned int parameters[5]; - parameters[0] = (unsigned int)r; - parameters[1] = (unsigned int)a; - parameters[2] = (unsigned int)e; - parameters[3] = (unsigned int)e_len; - parameters[4] = (unsigned int)n; - return SVC_cx_call(SYSCALL_cx_bn_mod_pow2_ID, parameters); -} - -cx_err_t cx_bn_mod_invert_nprime ( cx_bn_t r, const cx_bn_t a, const cx_bn_t n ) { - unsigned int parameters[3]; - parameters[0] = (unsigned int)r; - parameters[1] = (unsigned int)a; - parameters[2] = (unsigned int)n; - return SVC_cx_call(SYSCALL_cx_bn_mod_invert_nprime_ID, parameters); -} - -cx_err_t cx_bn_mod_u32_invert ( cx_bn_t r, uint32_t a, cx_bn_t n ) { - unsigned int parameters[3]; - parameters[0] = (unsigned int)r; - parameters[1] = (unsigned int)a; - parameters[2] = (unsigned int)n; - return SVC_cx_call(SYSCALL_cx_bn_mod_u32_invert_ID, parameters); -} - -cx_err_t cx_bn_is_prime ( const cx_bn_t n, bool *prime ) { - unsigned int parameters[2]; - parameters[0] = (unsigned int)n; - parameters[1] = (unsigned int)prime; - return SVC_cx_call(SYSCALL_cx_bn_is_prime_ID, parameters); -} - -cx_err_t cx_bn_next_prime ( cx_bn_t n ) { - unsigned int parameters[2]; - parameters[0] = (unsigned int)n; - parameters[1] = 0; - return SVC_cx_call(SYSCALL_cx_bn_next_prime_ID, parameters); -} - -cx_err_t cx_bn_rng ( cx_bn_t r, const cx_bn_t n ) { - unsigned int parameters[2]; - parameters[0] = (unsigned int)r; - parameters[1] = (unsigned int)n; - return SVC_cx_call(SYSCALL_cx_bn_rng_ID, parameters); -} - -cx_err_t cx_bn_gf2_n_mul(cx_bn_t r, const cx_bn_t a, const cx_bn_t b, const cx_bn_t n, const cx_bn_t h) { - unsigned int parameters[5]; - parameters[0] = (unsigned int)r; - parameters[1] = (unsigned int)a; - parameters[2] = (unsigned int)b; - parameters[3] = (unsigned int)n; - parameters[4] = (unsigned int)h; - return SVC_cx_call(SYSCALL_cx_bn_gf2_n_mul_ID, parameters); -} - -cx_err_t cx_mont_alloc ( cx_bn_mont_ctx_t * ctx, size_t length ) { - unsigned int parameters[2]; - parameters[0] = (unsigned int)ctx; - parameters[1] = (unsigned int)length; - return SVC_cx_call(SYSCALL_cx_mont_alloc_ID, parameters); -} - -cx_err_t cx_mont_init ( cx_bn_mont_ctx_t * ctx, const cx_bn_t n ) { - unsigned int parameters[2]; - parameters[0] = (unsigned int)ctx; - parameters[1] = (unsigned int)n; - return SVC_cx_call(SYSCALL_cx_mont_init_ID, parameters); +cx_err_t cx_bn_gf2_n_mul(cx_bn_t r, + const cx_bn_t a, + const cx_bn_t b, + const cx_bn_t n, + const cx_bn_t h) +{ + unsigned int parameters[5]; + parameters[0] = (unsigned int) r; + parameters[1] = (unsigned int) a; + parameters[2] = (unsigned int) b; + parameters[3] = (unsigned int) n; + parameters[4] = (unsigned int) h; + return SVC_cx_call(SYSCALL_cx_bn_gf2_n_mul_ID, parameters); } -cx_err_t cx_mont_init2 ( cx_bn_mont_ctx_t * ctx, const cx_bn_t n, const cx_bn_t h ) { - unsigned int parameters[3]; - parameters[0] = (unsigned int)ctx; - parameters[1] = (unsigned int)n; - parameters[2] = (unsigned int)h; - return SVC_cx_call(SYSCALL_cx_mont_init2_ID, parameters); +cx_err_t cx_mont_alloc(cx_bn_mont_ctx_t *ctx, size_t length) +{ + unsigned int parameters[2]; + parameters[0] = (unsigned int) ctx; + parameters[1] = (unsigned int) length; + return SVC_cx_call(SYSCALL_cx_mont_alloc_ID, parameters); } -cx_err_t cx_mont_to_montgomery ( cx_bn_t x, const cx_bn_t z, const cx_bn_mont_ctx_t * ctx ) { - unsigned int parameters[3]; - parameters[0] = (unsigned int)x; - parameters[1] = (unsigned int)z; - parameters[2] = (unsigned int)ctx; - return SVC_cx_call(SYSCALL_cx_mont_to_montgomery_ID, parameters); +cx_err_t cx_mont_init(cx_bn_mont_ctx_t *ctx, const cx_bn_t n) +{ + unsigned int parameters[2]; + parameters[0] = (unsigned int) ctx; + parameters[1] = (unsigned int) n; + return SVC_cx_call(SYSCALL_cx_mont_init_ID, parameters); } -cx_err_t cx_mont_from_montgomery ( cx_bn_t z, const cx_bn_t x, const cx_bn_mont_ctx_t * ctx ) { - unsigned int parameters[3]; - parameters[0] = (unsigned int)z; - parameters[1] = (unsigned int)x; - parameters[2] = (unsigned int)ctx; - return SVC_cx_call(SYSCALL_cx_mont_from_montgomery_ID, parameters); +cx_err_t cx_mont_init2(cx_bn_mont_ctx_t *ctx, const cx_bn_t n, const cx_bn_t h) +{ + unsigned int parameters[3]; + parameters[0] = (unsigned int) ctx; + parameters[1] = (unsigned int) n; + parameters[2] = (unsigned int) h; + return SVC_cx_call(SYSCALL_cx_mont_init2_ID, parameters); } -cx_err_t cx_mont_mul ( cx_bn_t r, const cx_bn_t a, const cx_bn_t b, const cx_bn_mont_ctx_t * ctx ) { - unsigned int parameters[4]; - parameters[0] = (unsigned int)r; - parameters[1] = (unsigned int)a; - parameters[2] = (unsigned int)b; - parameters[3] = (unsigned int)ctx; - return SVC_cx_call(SYSCALL_cx_mont_mul_ID, parameters); +cx_err_t cx_mont_to_montgomery(cx_bn_t x, const cx_bn_t z, const cx_bn_mont_ctx_t *ctx) +{ + unsigned int parameters[3]; + parameters[0] = (unsigned int) x; + parameters[1] = (unsigned int) z; + parameters[2] = (unsigned int) ctx; + return SVC_cx_call(SYSCALL_cx_mont_to_montgomery_ID, parameters); } -cx_err_t cx_mont_pow ( cx_bn_t r, const cx_bn_t a, const uint8_t * e, uint32_t e_len, const cx_bn_mont_ctx_t * ctx ) { - unsigned int parameters[5]; - parameters[0] = (unsigned int)r; - parameters[1] = (unsigned int)a; - parameters[2] = (unsigned int)e; - parameters[3] = (unsigned int)e_len; - parameters[4] = (unsigned int)ctx; - return SVC_cx_call(SYSCALL_cx_mont_pow_ID, parameters); +cx_err_t cx_mont_from_montgomery(cx_bn_t z, const cx_bn_t x, const cx_bn_mont_ctx_t *ctx) +{ + unsigned int parameters[3]; + parameters[0] = (unsigned int) z; + parameters[1] = (unsigned int) x; + parameters[2] = (unsigned int) ctx; + return SVC_cx_call(SYSCALL_cx_mont_from_montgomery_ID, parameters); } -cx_err_t cx_mont_pow_bn ( cx_bn_t r, const cx_bn_t a, const cx_bn_t e, const cx_bn_mont_ctx_t * ctx ) { - unsigned int parameters[4]; - parameters[0] = (unsigned int)r; - parameters[1] = (unsigned int)a; - parameters[2] = (unsigned int)e; - parameters[3] = (unsigned int)ctx; - return SVC_cx_call(SYSCALL_cx_mont_pow_bn_ID, parameters); +cx_err_t cx_mont_mul(cx_bn_t r, const cx_bn_t a, const cx_bn_t b, const cx_bn_mont_ctx_t *ctx) +{ + unsigned int parameters[4]; + parameters[0] = (unsigned int) r; + parameters[1] = (unsigned int) a; + parameters[2] = (unsigned int) b; + parameters[3] = (unsigned int) ctx; + return SVC_cx_call(SYSCALL_cx_mont_mul_ID, parameters); +} + +cx_err_t cx_mont_pow(cx_bn_t r, + const cx_bn_t a, + const uint8_t *e, + uint32_t e_len, + const cx_bn_mont_ctx_t *ctx) +{ + unsigned int parameters[5]; + parameters[0] = (unsigned int) r; + parameters[1] = (unsigned int) a; + parameters[2] = (unsigned int) e; + parameters[3] = (unsigned int) e_len; + parameters[4] = (unsigned int) ctx; + return SVC_cx_call(SYSCALL_cx_mont_pow_ID, parameters); } -cx_err_t cx_mont_invert_nprime ( cx_bn_t r, const cx_bn_t a, const cx_bn_mont_ctx_t * ctx ) { - unsigned int parameters[3]; - parameters[0] = (unsigned int)r; - parameters[1] = (unsigned int)a; - parameters[2] = (unsigned int)ctx; - return SVC_cx_call(SYSCALL_cx_mont_invert_nprime_ID, parameters); +cx_err_t cx_mont_pow_bn(cx_bn_t r, const cx_bn_t a, const cx_bn_t e, const cx_bn_mont_ctx_t *ctx) +{ + unsigned int parameters[4]; + parameters[0] = (unsigned int) r; + parameters[1] = (unsigned int) a; + parameters[2] = (unsigned int) e; + parameters[3] = (unsigned int) ctx; + return SVC_cx_call(SYSCALL_cx_mont_pow_bn_ID, parameters); } -cx_err_t cx_ecdomain_size ( cx_curve_t cv, size_t *length ) { - unsigned int parameters[2]; - parameters[0] = (unsigned int)cv; - parameters[1] = (unsigned int)length; - return SVC_cx_call(SYSCALL_cx_ecdomain_size_ID, parameters); +cx_err_t cx_mont_invert_nprime(cx_bn_t r, const cx_bn_t a, const cx_bn_mont_ctx_t *ctx) +{ + unsigned int parameters[3]; + parameters[0] = (unsigned int) r; + parameters[1] = (unsigned int) a; + parameters[2] = (unsigned int) ctx; + return SVC_cx_call(SYSCALL_cx_mont_invert_nprime_ID, parameters); } -cx_err_t cx_ecdomain_parameters_length ( cx_curve_t cv, size_t *length ) { - unsigned int parameters[2]; - parameters[0] = (unsigned int)cv; - parameters[1] = (unsigned int)length; - return SVC_cx_call(SYSCALL_cx_ecdomain_parameters_length_ID, parameters); -} - -cx_err_t cx_ecdomain_parameter ( cx_curve_t cv, cx_curve_dom_param_t id, uint8_t * p, uint32_t p_len ) { - unsigned int parameters[4]; - parameters[0] = (unsigned int)cv; - parameters[1] = (unsigned int)id; - parameters[2] = (unsigned int)p; - parameters[3] = (unsigned int)p_len; - return SVC_cx_call(SYSCALL_cx_ecdomain_parameter_ID, parameters); -} +cx_err_t cx_ecdomain_size(cx_curve_t cv, size_t *length) +{ + unsigned int parameters[2]; + parameters[0] = (unsigned int) cv; + parameters[1] = (unsigned int) length; + return SVC_cx_call(SYSCALL_cx_ecdomain_size_ID, parameters); +} -cx_err_t cx_ecdomain_parameter_bn ( cx_curve_t cv, cx_curve_dom_param_t id, cx_bn_t p ) { - unsigned int parameters[3]; - parameters[0] = (unsigned int)cv; - parameters[1] = (unsigned int)id; - parameters[2] = (unsigned int)p; - return SVC_cx_call(SYSCALL_cx_ecdomain_parameter_bn_ID, parameters); +cx_err_t cx_ecdomain_parameters_length(cx_curve_t cv, size_t *length) +{ + unsigned int parameters[2]; + parameters[0] = (unsigned int) cv; + parameters[1] = (unsigned int) length; + return SVC_cx_call(SYSCALL_cx_ecdomain_parameters_length_ID, parameters); } -cx_err_t cx_ecdomain_generator ( cx_curve_t cv, uint8_t * Gx, uint8_t * Gy, size_t len ) { - unsigned int parameters[4]; - parameters[0] = (unsigned int)cv; - parameters[1] = (unsigned int)Gx; - parameters[2] = (unsigned int)Gy; - parameters[3] = (unsigned int)len; - return SVC_cx_call(SYSCALL_cx_ecdomain_generator_ID, parameters); +cx_err_t cx_ecdomain_parameter(cx_curve_t cv, cx_curve_dom_param_t id, uint8_t *p, uint32_t p_len) +{ + unsigned int parameters[4]; + parameters[0] = (unsigned int) cv; + parameters[1] = (unsigned int) id; + parameters[2] = (unsigned int) p; + parameters[3] = (unsigned int) p_len; + return SVC_cx_call(SYSCALL_cx_ecdomain_parameter_ID, parameters); } - -cx_err_t cx_ecdomain_generator_bn ( cx_curve_t cv, cx_ecpoint_t * P ) { - unsigned int parameters[2]; - parameters[0] = (unsigned int)cv; - parameters[1] = (unsigned int)P; - return SVC_cx_call(SYSCALL_cx_ecdomain_generator_bn_ID, parameters); + +cx_err_t cx_ecdomain_parameter_bn(cx_curve_t cv, cx_curve_dom_param_t id, cx_bn_t p) +{ + unsigned int parameters[3]; + parameters[0] = (unsigned int) cv; + parameters[1] = (unsigned int) id; + parameters[2] = (unsigned int) p; + return SVC_cx_call(SYSCALL_cx_ecdomain_parameter_bn_ID, parameters); } -cx_err_t cx_ecpoint_alloc ( cx_ecpoint_t * P, cx_curve_t cv ) { - unsigned int parameters[2]; - parameters[0] = (unsigned int)P; - parameters[1] = (unsigned int)cv; - return SVC_cx_call(SYSCALL_cx_ecpoint_alloc_ID, parameters); +cx_err_t cx_ecdomain_generator(cx_curve_t cv, uint8_t *Gx, uint8_t *Gy, size_t len) +{ + unsigned int parameters[4]; + parameters[0] = (unsigned int) cv; + parameters[1] = (unsigned int) Gx; + parameters[2] = (unsigned int) Gy; + parameters[3] = (unsigned int) len; + return SVC_cx_call(SYSCALL_cx_ecdomain_generator_ID, parameters); } -cx_err_t cx_ecpoint_destroy ( cx_ecpoint_t * P ) { - unsigned int parameters[2]; - parameters[0] = (unsigned int)P; - parameters[1] = 0; - return SVC_cx_call(SYSCALL_cx_ecpoint_destroy_ID, parameters); +cx_err_t cx_ecdomain_generator_bn(cx_curve_t cv, cx_ecpoint_t *P) +{ + unsigned int parameters[2]; + parameters[0] = (unsigned int) cv; + parameters[1] = (unsigned int) P; + return SVC_cx_call(SYSCALL_cx_ecdomain_generator_bn_ID, parameters); } -cx_err_t cx_ecpoint_init ( cx_ecpoint_t * P, const uint8_t * x, size_t x_len, const uint8_t * y, size_t y_len ) { - unsigned int parameters[5]; - parameters[0] = (unsigned int)P; - parameters[1] = (unsigned int)x; - parameters[2] = (unsigned int)x_len; - parameters[3] = (unsigned int)y; - parameters[4] = (unsigned int)y_len; - return SVC_cx_call(SYSCALL_cx_ecpoint_init_ID, parameters); +cx_err_t cx_ecpoint_alloc(cx_ecpoint_t *P, cx_curve_t cv) +{ + unsigned int parameters[2]; + parameters[0] = (unsigned int) P; + parameters[1] = (unsigned int) cv; + return SVC_cx_call(SYSCALL_cx_ecpoint_alloc_ID, parameters); } -cx_err_t cx_ecpoint_init_bn ( cx_ecpoint_t * P, const cx_bn_t x, const cx_bn_t y ) { - unsigned int parameters[3]; - parameters[0] = (unsigned int)P; - parameters[1] = (unsigned int)x; - parameters[2] = (unsigned int)y; - return SVC_cx_call(SYSCALL_cx_ecpoint_init_bn_ID, parameters); +cx_err_t cx_ecpoint_destroy(cx_ecpoint_t *P) +{ + unsigned int parameters[2]; + parameters[0] = (unsigned int) P; + parameters[1] = 0; + return SVC_cx_call(SYSCALL_cx_ecpoint_destroy_ID, parameters); } -cx_err_t cx_ecpoint_export ( const cx_ecpoint_t * P, uint8_t * x, size_t x_len, uint8_t * y, size_t y_len ) { - unsigned int parameters[5]; - parameters[0] = (unsigned int)P; - parameters[1] = (unsigned int)x; - parameters[2] = (unsigned int)x_len; - parameters[3] = (unsigned int)y; - parameters[4] = (unsigned int)y_len; - return SVC_cx_call(SYSCALL_cx_ecpoint_export_ID, parameters); +cx_err_t cx_ecpoint_init(cx_ecpoint_t *P, + const uint8_t *x, + size_t x_len, + const uint8_t *y, + size_t y_len) +{ + unsigned int parameters[5]; + parameters[0] = (unsigned int) P; + parameters[1] = (unsigned int) x; + parameters[2] = (unsigned int) x_len; + parameters[3] = (unsigned int) y; + parameters[4] = (unsigned int) y_len; + return SVC_cx_call(SYSCALL_cx_ecpoint_init_ID, parameters); } -cx_err_t cx_ecpoint_export_bn ( const cx_ecpoint_t * P, cx_bn_t * x, cx_bn_t * y ) { - unsigned int parameters[3]; - parameters[0] = (unsigned int)P; - parameters[1] = (unsigned int)x; - parameters[2] = (unsigned int)y; - return SVC_cx_call(SYSCALL_cx_ecpoint_export_bn_ID, parameters); +cx_err_t cx_ecpoint_init_bn(cx_ecpoint_t *P, const cx_bn_t x, const cx_bn_t y) +{ + unsigned int parameters[3]; + parameters[0] = (unsigned int) P; + parameters[1] = (unsigned int) x; + parameters[2] = (unsigned int) y; + return SVC_cx_call(SYSCALL_cx_ecpoint_init_bn_ID, parameters); +} + +cx_err_t cx_ecpoint_export(const cx_ecpoint_t *P, + uint8_t *x, + size_t x_len, + uint8_t *y, + size_t y_len) +{ + unsigned int parameters[5]; + parameters[0] = (unsigned int) P; + parameters[1] = (unsigned int) x; + parameters[2] = (unsigned int) x_len; + parameters[3] = (unsigned int) y; + parameters[4] = (unsigned int) y_len; + return SVC_cx_call(SYSCALL_cx_ecpoint_export_ID, parameters); } -cx_err_t cx_ecpoint_compress ( const cx_ecpoint_t * P, uint8_t * xy_compressed, size_t xy_compressed_len, uint32_t * sign ) { - unsigned int parameters[4]; - parameters[0] = (unsigned int)P; - parameters[1] = (unsigned int)xy_compressed; - parameters[2] = (unsigned int)xy_compressed_len; - parameters[3] = (unsigned int)sign; - return SVC_cx_call(SYSCALL_cx_ecpoint_compress_ID, parameters); +cx_err_t cx_ecpoint_export_bn(const cx_ecpoint_t *P, cx_bn_t *x, cx_bn_t *y) +{ + unsigned int parameters[3]; + parameters[0] = (unsigned int) P; + parameters[1] = (unsigned int) x; + parameters[2] = (unsigned int) y; + return SVC_cx_call(SYSCALL_cx_ecpoint_export_bn_ID, parameters); } -cx_err_t cx_ecpoint_decompress ( cx_ecpoint_t * P, const uint8_t * xy_compressed, size_t xy_compressed_len, uint32_t sign ) { - unsigned int parameters[4]; - parameters[0] = (unsigned int)P; - parameters[1] = (unsigned int)xy_compressed; - parameters[2] = (unsigned int)xy_compressed_len; - parameters[3] = (unsigned int)sign; - return SVC_cx_call(SYSCALL_cx_ecpoint_decompress_ID, parameters); +cx_err_t cx_ecpoint_compress(const cx_ecpoint_t *P, + uint8_t *xy_compressed, + size_t xy_compressed_len, + uint32_t *sign) +{ + unsigned int parameters[4]; + parameters[0] = (unsigned int) P; + parameters[1] = (unsigned int) xy_compressed; + parameters[2] = (unsigned int) xy_compressed_len; + parameters[3] = (unsigned int) sign; + return SVC_cx_call(SYSCALL_cx_ecpoint_compress_ID, parameters); +} + +cx_err_t cx_ecpoint_decompress(cx_ecpoint_t *P, + const uint8_t *xy_compressed, + size_t xy_compressed_len, + uint32_t sign) +{ + unsigned int parameters[4]; + parameters[0] = (unsigned int) P; + parameters[1] = (unsigned int) xy_compressed; + parameters[2] = (unsigned int) xy_compressed_len; + parameters[3] = (unsigned int) sign; + return SVC_cx_call(SYSCALL_cx_ecpoint_decompress_ID, parameters); } -cx_err_t cx_ecpoint_add ( cx_ecpoint_t * R, const cx_ecpoint_t * P, const cx_ecpoint_t * Q ) { - unsigned int parameters[3]; - parameters[0] = (unsigned int)R; - parameters[1] = (unsigned int)P; - parameters[2] = (unsigned int)Q; - return SVC_cx_call(SYSCALL_cx_ecpoint_add_ID, parameters); +cx_err_t cx_ecpoint_add(cx_ecpoint_t *R, const cx_ecpoint_t *P, const cx_ecpoint_t *Q) +{ + unsigned int parameters[3]; + parameters[0] = (unsigned int) R; + parameters[1] = (unsigned int) P; + parameters[2] = (unsigned int) Q; + return SVC_cx_call(SYSCALL_cx_ecpoint_add_ID, parameters); } -cx_err_t cx_ecpoint_neg ( cx_ecpoint_t * P ) { - unsigned int parameters[2]; - parameters[0] = (unsigned int)P; - parameters[1] = 0; - return SVC_cx_call(SYSCALL_cx_ecpoint_neg_ID, parameters); +cx_err_t cx_ecpoint_neg(cx_ecpoint_t *P) +{ + unsigned int parameters[2]; + parameters[0] = (unsigned int) P; + parameters[1] = 0; + return SVC_cx_call(SYSCALL_cx_ecpoint_neg_ID, parameters); } -cx_err_t cx_ecpoint_scalarmul ( cx_ecpoint_t * P, const uint8_t * k, size_t k_len ) { - unsigned int parameters[3]; - parameters[0] = (unsigned int)P; - parameters[1] = (unsigned int)k; - parameters[2] = (unsigned int)k_len; - return SVC_cx_call(SYSCALL_cx_ecpoint_scalarmul_ID, parameters); +cx_err_t cx_ecpoint_scalarmul(cx_ecpoint_t *P, const uint8_t *k, size_t k_len) +{ + unsigned int parameters[3]; + parameters[0] = (unsigned int) P; + parameters[1] = (unsigned int) k; + parameters[2] = (unsigned int) k_len; + return SVC_cx_call(SYSCALL_cx_ecpoint_scalarmul_ID, parameters); } -cx_err_t cx_ecpoint_scalarmul_bn ( cx_ecpoint_t * P, const cx_bn_t bn_k ) { - unsigned int parameters[2]; - parameters[0] = (unsigned int)P; - parameters[1] = (unsigned int)bn_k; - return SVC_cx_call(SYSCALL_cx_ecpoint_scalarmul_bn_ID, parameters); +cx_err_t cx_ecpoint_scalarmul_bn(cx_ecpoint_t *P, const cx_bn_t bn_k) +{ + unsigned int parameters[2]; + parameters[0] = (unsigned int) P; + parameters[1] = (unsigned int) bn_k; + return SVC_cx_call(SYSCALL_cx_ecpoint_scalarmul_bn_ID, parameters); } -cx_err_t cx_ecpoint_rnd_scalarmul ( cx_ecpoint_t * P, const uint8_t * k, size_t k_len ) { - unsigned int parameters[3]; - parameters[0] = (unsigned int)P; - parameters[1] = (unsigned int)k; - parameters[2] = (unsigned int)k_len; - return SVC_cx_call(SYSCALL_cx_ecpoint_rnd_scalarmul_ID, parameters); +cx_err_t cx_ecpoint_rnd_scalarmul(cx_ecpoint_t *P, const uint8_t *k, size_t k_len) +{ + unsigned int parameters[3]; + parameters[0] = (unsigned int) P; + parameters[1] = (unsigned int) k; + parameters[2] = (unsigned int) k_len; + return SVC_cx_call(SYSCALL_cx_ecpoint_rnd_scalarmul_ID, parameters); } -cx_err_t cx_ecpoint_rnd_scalarmul_bn ( cx_ecpoint_t * P, const cx_bn_t bn_k ) { - unsigned int parameters[2]; - parameters[0] = (unsigned int)P; - parameters[1] = (unsigned int)bn_k; - return SVC_cx_call(SYSCALL_cx_ecpoint_rnd_scalarmul_bn_ID, parameters); +cx_err_t cx_ecpoint_rnd_scalarmul_bn(cx_ecpoint_t *P, const cx_bn_t bn_k) +{ + unsigned int parameters[2]; + parameters[0] = (unsigned int) P; + parameters[1] = (unsigned int) bn_k; + return SVC_cx_call(SYSCALL_cx_ecpoint_rnd_scalarmul_bn_ID, parameters); } #ifdef HAVE_FIXED_SCALAR_LENGTH -cx_err_t cx_ecpoint_rnd_fixed_scalarmul ( cx_ecpoint_t * P, const uint8_t * k, size_t k_len ) { - unsigned int parameters[3]; - parameters[0] = (unsigned int)P; - parameters[1] = (unsigned int)k; - parameters[2] = (unsigned int)k_len; - return SVC_cx_call(SYSCALL_cx_ecpoint_rnd_fixed_scalarmul_ID, parameters); -} -#endif // HAVE_FIXED_SCALAR_LENGTH - -cx_err_t cx_ecpoint_double_scalarmul ( cx_ecpoint_t * R, cx_ecpoint_t *P, cx_ecpoint_t *Q, const uint8_t * k, size_t k_len, const uint8_t * r, size_t r_len ) { - unsigned int parameters[7]; - parameters[0] = (unsigned int)R; - parameters[1] = (unsigned int)P; - parameters[2] = (unsigned int)Q; - parameters[3] = (unsigned int)k; - parameters[4] = (unsigned int)k_len; - parameters[5] = (unsigned int)r; - parameters[6] = (unsigned int)r_len; - return SVC_cx_call(SYSCALL_cx_ecpoint_double_scalarmul_ID, parameters); -} - -cx_err_t cx_ecpoint_double_scalarmul_bn ( cx_ecpoint_t * R, cx_ecpoint_t *P, cx_ecpoint_t *Q, const cx_bn_t bn_k, const cx_bn_t bn_r ) { - unsigned int parameters[5]; - parameters[0] = (unsigned int)R; - parameters[1] = (unsigned int)P; - parameters[2] = (unsigned int)Q; - parameters[3] = (unsigned int)bn_k; - parameters[4] = (unsigned int)bn_r; - return SVC_cx_call(SYSCALL_cx_ecpoint_double_scalarmul_bn_ID, parameters); -} - -cx_err_t cx_ecpoint_cmp(const cx_ecpoint_t * P, const cx_ecpoint_t * Q, bool *is_equal) { - unsigned int parameters[3]; - parameters[0] = (unsigned int)P; - parameters[1] = (unsigned int)Q; - parameters[2] = (unsigned int)is_equal; - return SVC_cx_call(SYSCALL_cx_ecpoint_cmp_ID, parameters); -} - -cx_err_t cx_ecpoint_is_on_curve ( const cx_ecpoint_t * R, bool *is_on_curve ) { - unsigned int parameters[2]; - parameters[0] = (unsigned int)R; - parameters[1] = (unsigned int)is_on_curve; - return SVC_cx_call(SYSCALL_cx_ecpoint_is_on_curve_ID, parameters); -} - -cx_err_t cx_ecpoint_is_at_infinity( const cx_ecpoint_t *R, bool *is_infinite ) { - unsigned int parameters[2]; - parameters[0] = (unsigned int)R; - parameters[1] = (unsigned int)is_infinite; - return SVC_cx_call(SYSCALL_cx_ecpoint_is_at_infinity_ID, parameters); +cx_err_t cx_ecpoint_rnd_fixed_scalarmul(cx_ecpoint_t *P, const uint8_t *k, size_t k_len) +{ + unsigned int parameters[3]; + parameters[0] = (unsigned int) P; + parameters[1] = (unsigned int) k; + parameters[2] = (unsigned int) k_len; + return SVC_cx_call(SYSCALL_cx_ecpoint_rnd_fixed_scalarmul_ID, parameters); +} +#endif // HAVE_FIXED_SCALAR_LENGTH + +cx_err_t cx_ecpoint_double_scalarmul(cx_ecpoint_t *R, + cx_ecpoint_t *P, + cx_ecpoint_t *Q, + const uint8_t *k, + size_t k_len, + const uint8_t *r, + size_t r_len) +{ + unsigned int parameters[7]; + parameters[0] = (unsigned int) R; + parameters[1] = (unsigned int) P; + parameters[2] = (unsigned int) Q; + parameters[3] = (unsigned int) k; + parameters[4] = (unsigned int) k_len; + parameters[5] = (unsigned int) r; + parameters[6] = (unsigned int) r_len; + return SVC_cx_call(SYSCALL_cx_ecpoint_double_scalarmul_ID, parameters); +} + +cx_err_t cx_ecpoint_double_scalarmul_bn(cx_ecpoint_t *R, + cx_ecpoint_t *P, + cx_ecpoint_t *Q, + const cx_bn_t bn_k, + const cx_bn_t bn_r) +{ + unsigned int parameters[5]; + parameters[0] = (unsigned int) R; + parameters[1] = (unsigned int) P; + parameters[2] = (unsigned int) Q; + parameters[3] = (unsigned int) bn_k; + parameters[4] = (unsigned int) bn_r; + return SVC_cx_call(SYSCALL_cx_ecpoint_double_scalarmul_bn_ID, parameters); +} + +cx_err_t cx_ecpoint_cmp(const cx_ecpoint_t *P, const cx_ecpoint_t *Q, bool *is_equal) +{ + unsigned int parameters[3]; + parameters[0] = (unsigned int) P; + parameters[1] = (unsigned int) Q; + parameters[2] = (unsigned int) is_equal; + return SVC_cx_call(SYSCALL_cx_ecpoint_cmp_ID, parameters); +} + +cx_err_t cx_ecpoint_is_on_curve(const cx_ecpoint_t *R, bool *is_on_curve) +{ + unsigned int parameters[2]; + parameters[0] = (unsigned int) R; + parameters[1] = (unsigned int) is_on_curve; + return SVC_cx_call(SYSCALL_cx_ecpoint_is_on_curve_ID, parameters); +} + +cx_err_t cx_ecpoint_is_at_infinity(const cx_ecpoint_t *R, bool *is_infinite) +{ + unsigned int parameters[2]; + parameters[0] = (unsigned int) R; + parameters[1] = (unsigned int) is_infinite; + return SVC_cx_call(SYSCALL_cx_ecpoint_is_at_infinity_ID, parameters); } #ifdef HAVE_X25519 -cx_err_t cx_ecpoint_x25519(const cx_bn_t u, const uint8_t *k, size_t k_len) { - unsigned int parameters[3]; - parameters[0] = (unsigned int)u; - parameters[1] = (unsigned int)k; - parameters[2] = (unsigned int)k_len; - return SVC_cx_call(SYSCALL_cx_ecpoint_x25519_ID, parameters); +cx_err_t cx_ecpoint_x25519(const cx_bn_t u, const uint8_t *k, size_t k_len) +{ + unsigned int parameters[3]; + parameters[0] = (unsigned int) u; + parameters[1] = (unsigned int) k; + parameters[2] = (unsigned int) k_len; + return SVC_cx_call(SYSCALL_cx_ecpoint_x25519_ID, parameters); } -#endif // HAVE_X25519 +#endif // HAVE_X25519 #ifdef HAVE_X448 -cx_err_t cx_ecpoint_x448(const cx_bn_t u, const uint8_t *k, size_t k_len) { - unsigned int parameters[3]; - parameters[0] = (unsigned int)u; - parameters[1] = (unsigned int)k; - parameters[2] = (unsigned int)k_len; - return SVC_cx_call(SYSCALL_cx_ecpoint_x448_ID, parameters); +cx_err_t cx_ecpoint_x448(const cx_bn_t u, const uint8_t *k, size_t k_len) +{ + unsigned int parameters[3]; + parameters[0] = (unsigned int) u; + parameters[1] = (unsigned int) k; + parameters[2] = (unsigned int) k_len; + return SVC_cx_call(SYSCALL_cx_ecpoint_x448_ID, parameters); } -#endif // HAVE_X448 +#endif // HAVE_X448 #ifdef HAVE_BLS -cx_err_t ox_bls12381_sign(const cx_ecfp_384_private_key_t *key, const uint8_t * message, size_t message_len, uint8_t * signature, size_t signature_len) { - unsigned int parameters [5]; - parameters[0] = (unsigned int)key; - parameters[1] = (unsigned int)message; - parameters[2] = (unsigned int)message_len; - parameters[3] = (unsigned int)signature; - parameters[4] = (unsigned int)signature_len; - return SVC_cx_call(SYSCALL_ox_bls12381_sign_ID, parameters); -} - -cx_err_t cx_bls12381_key_gen(uint8_t mode, - const uint8_t *secret, size_t secret_len, - const uint8_t *salt, size_t salt_len, - uint8_t *key_info, size_t key_info_len, +cx_err_t ox_bls12381_sign(const cx_ecfp_384_private_key_t *key, + const uint8_t *message, + size_t message_len, + uint8_t *signature, + size_t signature_len) +{ + unsigned int parameters[5]; + parameters[0] = (unsigned int) key; + parameters[1] = (unsigned int) message; + parameters[2] = (unsigned int) message_len; + parameters[3] = (unsigned int) signature; + parameters[4] = (unsigned int) signature_len; + return SVC_cx_call(SYSCALL_ox_bls12381_sign_ID, parameters); +} + +cx_err_t cx_bls12381_key_gen(uint8_t mode, + const uint8_t *secret, + size_t secret_len, + const uint8_t *salt, + size_t salt_len, + uint8_t *key_info, + size_t key_info_len, cx_ecfp_384_private_key_t *private_key, - uint8_t *public_key, - size_t public_key_len) { - unsigned int parameters[10]; - parameters[0] = (unsigned int)mode; - parameters[1] = (unsigned int)secret; - parameters[2] = (unsigned int)secret_len; - parameters[3] = (unsigned int)salt; - parameters[4] = (unsigned int)salt_len; - parameters[5] = (unsigned int)key_info; - parameters[6] = (unsigned int)key_info_len; - parameters[7] = (unsigned int)private_key; - parameters[8] = (unsigned int)public_key; - parameters[9] = (unsigned int)public_key_len; - return SVC_cx_call(SYSCALL_cx_bls12381_key_gen_ID, parameters); -} - -cx_err_t cx_hash_to_field(const uint8_t *msg, size_t msg_len, const uint8_t *dst, size_t dst_len, uint8_t *hash, size_t hash_len) { - unsigned int parameters [6]; - parameters[0] = (unsigned int)msg; - parameters[1] = (unsigned int)msg_len; - parameters[2] = (unsigned int)dst; - parameters[3] = (unsigned int)dst_len; - parameters[4] = (unsigned int)hash; - parameters[5] = (unsigned int)hash_len; - return SVC_cx_call(SYSCALL_cx_hash_to_field_ID, parameters); -} - -cx_err_t cx_bls12381_aggregate(const uint8_t *in, size_t in_len, bool first, uint8_t *aggregated_signature, size_t signature_len) { - unsigned int parameters [5]; - parameters[0] = (unsigned int)in; - parameters[1] = (unsigned int)in_len; - parameters[2] = (unsigned int)first; - parameters[3] = (unsigned int)aggregated_signature; - parameters[4] = (unsigned int)signature_len; - return SVC_cx_call(SYSCALL_cx_bls12381_aggregate_ID, parameters); -} -#endif // HAVE_BLS + uint8_t *public_key, + size_t public_key_len) +{ + unsigned int parameters[10]; + parameters[0] = (unsigned int) mode; + parameters[1] = (unsigned int) secret; + parameters[2] = (unsigned int) secret_len; + parameters[3] = (unsigned int) salt; + parameters[4] = (unsigned int) salt_len; + parameters[5] = (unsigned int) key_info; + parameters[6] = (unsigned int) key_info_len; + parameters[7] = (unsigned int) private_key; + parameters[8] = (unsigned int) public_key; + parameters[9] = (unsigned int) public_key_len; + return SVC_cx_call(SYSCALL_cx_bls12381_key_gen_ID, parameters); +} + +cx_err_t cx_hash_to_field(const uint8_t *msg, + size_t msg_len, + const uint8_t *dst, + size_t dst_len, + uint8_t *hash, + size_t hash_len) +{ + unsigned int parameters[6]; + parameters[0] = (unsigned int) msg; + parameters[1] = (unsigned int) msg_len; + parameters[2] = (unsigned int) dst; + parameters[3] = (unsigned int) dst_len; + parameters[4] = (unsigned int) hash; + parameters[5] = (unsigned int) hash_len; + return SVC_cx_call(SYSCALL_cx_hash_to_field_ID, parameters); +} + +cx_err_t cx_bls12381_aggregate(const uint8_t *in, + size_t in_len, + bool first, + uint8_t *aggregated_signature, + size_t signature_len) +{ + unsigned int parameters[5]; + parameters[0] = (unsigned int) in; + parameters[1] = (unsigned int) in_len; + parameters[2] = (unsigned int) first; + parameters[3] = (unsigned int) aggregated_signature; + parameters[4] = (unsigned int) signature_len; + return SVC_cx_call(SYSCALL_cx_bls12381_aggregate_ID, parameters); +} +#endif // HAVE_BLS #if defined(HAVE_VSS) -cx_err_t cx_vss_generate_shares(cx_vss_share_t *shares, +cx_err_t cx_vss_generate_shares(cx_vss_share_t *shares, cx_vss_commitment_t *commits, - const uint8_t *point, - size_t point_len, - const uint8_t *seed, - size_t seed_len, - const uint8_t *secret, - size_t secret_len, - uint8_t shares_number, - uint8_t threshold) { - unsigned int parameters[10]; - parameters[0] = (unsigned int)shares; - parameters[1] = (unsigned int)commits; - parameters[2] = (unsigned int)point; - parameters[3] = (unsigned int)point_len; - parameters[4] = (unsigned int)seed; - parameters[5] = (unsigned int)seed_len; - parameters[6] = (unsigned int)secret; - parameters[7] = (unsigned int)secret_len; - parameters[8] = (unsigned int)shares_number; - parameters[9] = (unsigned int)threshold; - return SVC_cx_call(SYSCALL_cx_vss_generate_shares_ID, parameters); -} - -cx_err_t cx_vss_combine_shares(uint8_t *secret, - size_t secret_len, + const uint8_t *point, + size_t point_len, + const uint8_t *seed, + size_t seed_len, + const uint8_t *secret, + size_t secret_len, + uint8_t shares_number, + uint8_t threshold) +{ + unsigned int parameters[10]; + parameters[0] = (unsigned int) shares; + parameters[1] = (unsigned int) commits; + parameters[2] = (unsigned int) point; + parameters[3] = (unsigned int) point_len; + parameters[4] = (unsigned int) seed; + parameters[5] = (unsigned int) seed_len; + parameters[6] = (unsigned int) secret; + parameters[7] = (unsigned int) secret_len; + parameters[8] = (unsigned int) shares_number; + parameters[9] = (unsigned int) threshold; + return SVC_cx_call(SYSCALL_cx_vss_generate_shares_ID, parameters); +} + +cx_err_t cx_vss_combine_shares(uint8_t *secret, + size_t secret_len, cx_vss_share_t *shares, - uint8_t threshold) { - unsigned int parameters[4]; - parameters[0] = (unsigned int)secret; - parameters[1] = (unsigned int)secret_len; - parameters[2] = (unsigned int)shares; - parameters[3] = (unsigned int)threshold; - return SVC_cx_call(SYSCALL_cx_vss_combine_shares_ID, parameters); + uint8_t threshold) +{ + unsigned int parameters[4]; + parameters[0] = (unsigned int) secret; + parameters[1] = (unsigned int) secret_len; + parameters[2] = (unsigned int) shares; + parameters[3] = (unsigned int) threshold; + return SVC_cx_call(SYSCALL_cx_vss_combine_shares_ID, parameters); } cx_err_t cx_vss_verify_commits(cx_vss_commitment_t *commitments, - uint8_t threshold, + uint8_t threshold, cx_vss_commitment_t *share_commitment, - uint32_t share_index, - bool *verified) { - unsigned int parameters[5]; - parameters[0] = (unsigned int)commitments; - parameters[1] = (unsigned int)threshold; - parameters[2] = (unsigned int)share_commitment; - parameters[3] = (unsigned int)share_index; - parameters[4] = (unsigned int)verified; - return SVC_cx_call(SYSCALL_cx_vss_verify_commits_ID, parameters); -} -#endif // HAVE_VSS - -uint32_t cx_crc32_hw ( const void * buf, size_t len ) { - unsigned int parameters[2]; - parameters[0] = (unsigned int)buf; - parameters[1] = (unsigned int)len; - return (uint32_t) SVC_cx_call(SYSCALL_cx_crc32_hw_ID, parameters); -} - -cx_err_t cx_get_random_bytes(void *buffer, size_t len) { - unsigned int parameters[2 + 2]; - parameters[0] = (unsigned int)buffer; - parameters[1] = (unsigned int)len; - return SVC_cx_call(SYSCALL_cx_get_random_bytes_ID, parameters); -} - -void cx_trng_get_random_data ( uint8_t * buf, size_t size ) { - unsigned int parameters[2]; - parameters[0] = (unsigned int)buf; - parameters[1] = (unsigned int)size; - SVC_cx_call(SYSCALL_cx_trng_get_random_data_ID, parameters); -} - -void os_perso_erase_all ( void ) { - unsigned int parameters[2]; - parameters[1] = 0; - SVC_Call(SYSCALL_os_perso_erase_all_ID, parameters); - return; -} - -void os_perso_set_seed ( unsigned int identity, unsigned int algorithm, unsigned char * seed, unsigned int length ) { - unsigned int parameters[4]; - parameters[0] = (unsigned int)identity; - parameters[1] = (unsigned int)algorithm; - parameters[2] = (unsigned int)seed; - parameters[3] = (unsigned int)length; - SVC_Call(SYSCALL_os_perso_set_seed_ID, parameters); - return; -} - -void os_perso_derive_and_set_seed ( unsigned char identity, const char * prefix, unsigned int prefix_length, const char * passphrase, unsigned int passphrase_length, const char * words, unsigned int words_length ) { - unsigned int parameters[7]; - parameters[0] = (unsigned int)identity; - parameters[1] = (unsigned int)prefix; - parameters[2] = (unsigned int)prefix_length; - parameters[3] = (unsigned int)passphrase; - parameters[4] = (unsigned int)passphrase_length; - parameters[5] = (unsigned int)words; - parameters[6] = (unsigned int)words_length; - SVC_Call(SYSCALL_os_perso_derive_and_set_seed_ID, parameters); - return; + uint32_t share_index, + bool *verified) +{ + unsigned int parameters[5]; + parameters[0] = (unsigned int) commitments; + parameters[1] = (unsigned int) threshold; + parameters[2] = (unsigned int) share_commitment; + parameters[3] = (unsigned int) share_index; + parameters[4] = (unsigned int) verified; + return SVC_cx_call(SYSCALL_cx_vss_verify_commits_ID, parameters); } +#endif // HAVE_VSS -#if defined(HAVE_VAULT_RECOVERY_ALGO) -void os_perso_derive_and_prepare_seed(const char* words, unsigned int words_length, uint8_t *vault_recovery_work_buffer) { - unsigned int parameters[3]; - parameters[0] = (unsigned int)words; - parameters[1] = (unsigned int)words_length; - parameters[2] = (unsigned int)vault_recovery_work_buffer; - SVC_Call(SYSCALL_os_perso_derive_and_prepare_seed_ID, parameters); - return; +uint32_t cx_crc32_hw(const void *buf, size_t len) +{ + unsigned int parameters[2]; + parameters[0] = (unsigned int) buf; + parameters[1] = (unsigned int) len; + return (uint32_t) SVC_cx_call(SYSCALL_cx_crc32_hw_ID, parameters); } -void os_perso_derive_and_xor_seed(uint8_t *vault_recovery_work_buffer) { - unsigned int parameters[2]; - parameters[0] = (unsigned int)vault_recovery_work_buffer; - SVC_Call(SYSCALL_os_perso_derive_and_xor_seed_ID, parameters); - return; +cx_err_t cx_get_random_bytes(void *buffer, size_t len) +{ + unsigned int parameters[2 + 2]; + parameters[0] = (unsigned int) buffer; + parameters[1] = (unsigned int) len; + return SVC_cx_call(SYSCALL_cx_get_random_bytes_ID, parameters); } -unsigned char os_perso_get_seed_algorithm(void) { - unsigned int parameters[2]; - parameters[1] = 0; - return (unsigned char)SVC_Call(SYSCALL_os_perso_get_seed_algorithm_ID, parameters); +void cx_trng_get_random_data(uint8_t *buf, size_t size) +{ + unsigned int parameters[2]; + parameters[0] = (unsigned int) buf; + parameters[1] = (unsigned int) size; + SVC_cx_call(SYSCALL_cx_trng_get_random_data_ID, parameters); } -#endif // HAVE_VAULT_RECOVERY_ALGO -#if defined(HAVE_RECOVER) -void os_perso_master_seed(uint8_t *master_seed, size_t length, os_action_t action) { - unsigned int parameters[3]; - parameters[0] = (unsigned int)master_seed; - parameters[1] = (unsigned int)length; - parameters[2] = (unsigned int)action; - SVC_Call(SYSCALL_os_perso_master_seed_ID, parameters); - return; -} - -void os_perso_recover_state(uint8_t *state, os_action_t action) { - unsigned int parameters[2]; - parameters[0] = (unsigned int)state; - parameters[1] = (unsigned int)action; - SVC_Call(SYSCALL_os_perso_recover_state_ID, parameters); - return; -} - -#endif // HAVE_RECOVER - -void os_perso_set_words ( const unsigned char * words, unsigned int length ) { - unsigned int parameters[2]; - parameters[0] = (unsigned int)words; - parameters[1] = (unsigned int)length; - SVC_Call(SYSCALL_os_perso_set_words_ID, parameters); - return; -} - -void os_perso_finalize ( void ) { - unsigned int parameters[2]; - parameters[1] = 0; - SVC_Call(SYSCALL_os_perso_finalize_ID, parameters); - return; -} - -bolos_bool_t os_perso_isonboarded ( void ) { - unsigned int parameters[2]; - parameters[1] = 0; - return (bolos_bool_t) SVC_Call(SYSCALL_os_perso_isonboarded_ID, parameters); -} - -void os_perso_set_onboarding_status(unsigned int state, unsigned int count, unsigned int total) { - unsigned int parameters [3]; - parameters[0] = (unsigned int)state; - parameters[1] = (unsigned int)count; - parameters[2] = (unsigned int)total; - SVC_Call(SYSCALL_os_perso_setonboardingstatus_ID, parameters); - return; -} - -void os_perso_derive_node_bip32 ( cx_curve_t curve, const unsigned int * path, unsigned int pathLength, unsigned char * privateKey, unsigned char * chain ) { - unsigned int parameters[5]; - parameters[0] = (unsigned int)curve; - parameters[1] = (unsigned int)path; - parameters[2] = (unsigned int)pathLength; - parameters[3] = (unsigned int)privateKey; - parameters[4] = (unsigned int)chain; - SVC_Call(SYSCALL_os_perso_derive_node_bip32_ID, parameters); - return; -} - -void os_perso_derive_node_with_seed_key ( unsigned int mode, cx_curve_t curve, const unsigned int * path, unsigned int pathLength, unsigned char * privateKey, unsigned char * chain, unsigned char * seed_key, unsigned int seed_key_length ) { - unsigned int parameters[8]; - parameters[0] = (unsigned int)mode; - parameters[1] = (unsigned int)curve; - parameters[2] = (unsigned int)path; - parameters[3] = (unsigned int)pathLength; - parameters[4] = (unsigned int)privateKey; - parameters[5] = (unsigned int)chain; - parameters[6] = (unsigned int)seed_key; - parameters[7] = (unsigned int)seed_key_length; - SVC_Call(SYSCALL_os_perso_derive_node_with_seed_key_ID, parameters); - return; -} - -void os_perso_derive_eip2333 ( cx_curve_t curve, const unsigned int * path, unsigned int pathLength, unsigned char * privateKey ) { - unsigned int parameters[4]; - parameters[0] = (unsigned int)curve; - parameters[1] = (unsigned int)path; - parameters[2] = (unsigned int)pathLength; - parameters[3] = (unsigned int)privateKey; - SVC_Call(SYSCALL_os_perso_derive_eip2333_ID, parameters); - return; +void os_perso_erase_all(void) +{ + unsigned int parameters[2]; + parameters[1] = 0; + SVC_Call(SYSCALL_os_perso_erase_all_ID, parameters); + return; } -#if defined(HAVE_SEED_COOKIE) -bolos_bool_t os_perso_seed_cookie ( unsigned char * seed_cookie ) { - unsigned int parameters[1]; - parameters[0] = (unsigned int)seed_cookie; - return (bolos_bool_t) SVC_Call(SYSCALL_os_perso_seed_cookie_ID, parameters); +void os_perso_set_seed(unsigned int identity, + unsigned int algorithm, + unsigned char *seed, + unsigned int length) +{ + unsigned int parameters[4]; + parameters[0] = (unsigned int) identity; + parameters[1] = (unsigned int) algorithm; + parameters[2] = (unsigned int) seed; + parameters[3] = (unsigned int) length; + SVC_Call(SYSCALL_os_perso_set_seed_ID, parameters); + return; +} + +void os_perso_derive_and_set_seed(unsigned char identity, + const char *prefix, + unsigned int prefix_length, + const char *passphrase, + unsigned int passphrase_length, + const char *words, + unsigned int words_length) +{ + unsigned int parameters[7]; + parameters[0] = (unsigned int) identity; + parameters[1] = (unsigned int) prefix; + parameters[2] = (unsigned int) prefix_length; + parameters[3] = (unsigned int) passphrase; + parameters[4] = (unsigned int) passphrase_length; + parameters[5] = (unsigned int) words; + parameters[6] = (unsigned int) words_length; + SVC_Call(SYSCALL_os_perso_derive_and_set_seed_ID, parameters); + return; } -#endif // HAVE_SEED_COOKIE -unsigned int os_endorsement_get_code_hash ( unsigned char * buffer ) { - unsigned int parameters[2]; - parameters[0] = (unsigned int)buffer; - parameters[1] = 0; - return (unsigned int) SVC_Call(SYSCALL_os_endorsement_get_code_hash_ID, parameters); +#if defined(HAVE_VAULT_RECOVERY_ALGO) +void os_perso_derive_and_prepare_seed(const char *words, + unsigned int words_length, + uint8_t *vault_recovery_work_buffer) +{ + unsigned int parameters[3]; + parameters[0] = (unsigned int) words; + parameters[1] = (unsigned int) words_length; + parameters[2] = (unsigned int) vault_recovery_work_buffer; + SVC_Call(SYSCALL_os_perso_derive_and_prepare_seed_ID, parameters); + return; } -unsigned int os_endorsement_get_public_key ( unsigned char index, unsigned char * buffer, unsigned char * length ) { - unsigned int parameters[3]; - parameters[0] = (unsigned int)index; - parameters[1] = (unsigned int)buffer; - parameters[2] = (unsigned int)length; - return (unsigned int) SVC_Call(SYSCALL_os_endorsement_get_public_key_ID, parameters); +void os_perso_derive_and_xor_seed(uint8_t *vault_recovery_work_buffer) +{ + unsigned int parameters[2]; + parameters[0] = (unsigned int) vault_recovery_work_buffer; + SVC_Call(SYSCALL_os_perso_derive_and_xor_seed_ID, parameters); + return; } -unsigned int os_endorsement_get_public_key_certificate ( unsigned char index, unsigned char * buffer, unsigned char * length ) { - unsigned int parameters[3]; - parameters[0] = (unsigned int)index; - parameters[1] = (unsigned int)buffer; - parameters[2] = (unsigned int)length; - return (unsigned int) SVC_Call(SYSCALL_os_endorsement_get_public_key_certificate_ID, parameters); +unsigned char os_perso_get_seed_algorithm(void) +{ + unsigned int parameters[2]; + parameters[1] = 0; + return (unsigned char) SVC_Call(SYSCALL_os_perso_get_seed_algorithm_ID, parameters); } +#endif // HAVE_VAULT_RECOVERY_ALGO -unsigned int os_endorsement_key1_get_app_secret ( unsigned char * buffer ) { - unsigned int parameters[2]; - parameters[0] = (unsigned int)buffer; - parameters[1] = 0; - return (unsigned int) SVC_Call(SYSCALL_os_endorsement_key1_get_app_secret_ID, parameters); +#if defined(HAVE_RECOVER) +void os_perso_master_seed(uint8_t *master_seed, size_t length, os_action_t action) +{ + unsigned int parameters[3]; + parameters[0] = (unsigned int) master_seed; + parameters[1] = (unsigned int) length; + parameters[2] = (unsigned int) action; + SVC_Call(SYSCALL_os_perso_master_seed_ID, parameters); + return; } -unsigned int os_endorsement_key1_sign_data ( unsigned char * src, unsigned int srcLength, unsigned char * signature ) { - unsigned int parameters[3]; - parameters[0] = (unsigned int)src; - parameters[1] = (unsigned int)srcLength; - parameters[2] = (unsigned int)signature; - return (unsigned int) SVC_Call(SYSCALL_os_endorsement_key1_sign_data_ID, parameters); +void os_perso_recover_state(uint8_t *state, os_action_t action) +{ + unsigned int parameters[2]; + parameters[0] = (unsigned int) state; + parameters[1] = (unsigned int) action; + SVC_Call(SYSCALL_os_perso_recover_state_ID, parameters); + return; } -unsigned int os_endorsement_key2_derive_sign_data ( unsigned char * src, unsigned int srcLength, unsigned char * signature ) { - unsigned int parameters[3]; - parameters[0] = (unsigned int)src; - parameters[1] = (unsigned int)srcLength; - parameters[2] = (unsigned int)signature; - return (unsigned int) SVC_Call(SYSCALL_os_endorsement_key2_derive_sign_data_ID, parameters); +#endif // HAVE_RECOVER + +void os_perso_set_words(const unsigned char *words, unsigned int length) +{ + unsigned int parameters[2]; + parameters[0] = (unsigned int) words; + parameters[1] = (unsigned int) length; + SVC_Call(SYSCALL_os_perso_set_words_ID, parameters); + return; } -void os_perso_set_pin ( unsigned int identity, const unsigned char * pin, unsigned int length, bool update_crc ) { - unsigned int parameters[4]; - parameters[0] = (unsigned int)identity; - parameters[1] = (unsigned int)pin; - parameters[2] = (unsigned int)length; - parameters[3] = (unsigned int)update_crc; - SVC_Call(SYSCALL_os_perso_set_pin_ID, parameters); - return; +void os_perso_finalize(void) +{ + unsigned int parameters[2]; + parameters[1] = 0; + SVC_Call(SYSCALL_os_perso_finalize_ID, parameters); + return; } -void os_perso_set_current_identity_pin ( unsigned char * pin, unsigned int length ) { - unsigned int parameters[2]; - parameters[0] = (unsigned int)pin; - parameters[1] = (unsigned int)length; - SVC_Call(SYSCALL_os_perso_set_current_identity_pin_ID, parameters); - return; +bolos_bool_t os_perso_isonboarded(void) +{ + unsigned int parameters[2]; + parameters[1] = 0; + return (bolos_bool_t) SVC_Call(SYSCALL_os_perso_isonboarded_ID, parameters); } -bolos_bool_t os_perso_is_pin_set ( void ) { - unsigned int parameters[2]; - parameters[1] = 0; - return (bolos_bool_t) SVC_Call(SYSCALL_os_perso_is_pin_set_ID, parameters); +void os_perso_set_onboarding_status(unsigned int state, unsigned int count, unsigned int total) +{ + unsigned int parameters[3]; + parameters[0] = (unsigned int) state; + parameters[1] = (unsigned int) count; + parameters[2] = (unsigned int) total; + SVC_Call(SYSCALL_os_perso_setonboardingstatus_ID, parameters); + return; +} + +void os_perso_derive_node_bip32(cx_curve_t curve, + const unsigned int *path, + unsigned int pathLength, + unsigned char *privateKey, + unsigned char *chain) +{ + unsigned int parameters[5]; + parameters[0] = (unsigned int) curve; + parameters[1] = (unsigned int) path; + parameters[2] = (unsigned int) pathLength; + parameters[3] = (unsigned int) privateKey; + parameters[4] = (unsigned int) chain; + SVC_Call(SYSCALL_os_perso_derive_node_bip32_ID, parameters); + return; +} + +void os_perso_derive_node_with_seed_key(unsigned int mode, + cx_curve_t curve, + const unsigned int *path, + unsigned int pathLength, + unsigned char *privateKey, + unsigned char *chain, + unsigned char *seed_key, + unsigned int seed_key_length) +{ + unsigned int parameters[8]; + parameters[0] = (unsigned int) mode; + parameters[1] = (unsigned int) curve; + parameters[2] = (unsigned int) path; + parameters[3] = (unsigned int) pathLength; + parameters[4] = (unsigned int) privateKey; + parameters[5] = (unsigned int) chain; + parameters[6] = (unsigned int) seed_key; + parameters[7] = (unsigned int) seed_key_length; + SVC_Call(SYSCALL_os_perso_derive_node_with_seed_key_ID, parameters); + return; +} + +void os_perso_derive_eip2333(cx_curve_t curve, + const unsigned int *path, + unsigned int pathLength, + unsigned char *privateKey) +{ + unsigned int parameters[4]; + parameters[0] = (unsigned int) curve; + parameters[1] = (unsigned int) path; + parameters[2] = (unsigned int) pathLength; + parameters[3] = (unsigned int) privateKey; + SVC_Call(SYSCALL_os_perso_derive_eip2333_ID, parameters); + return; } -bolos_bool_t os_global_pin_is_validated ( void ) { - unsigned int parameters[2]; - parameters[1] = 0; - return (bolos_bool_t) SVC_Call(SYSCALL_os_global_pin_is_validated_ID, parameters); +#if defined(HAVE_SEED_COOKIE) +bolos_bool_t os_perso_seed_cookie(unsigned char *seed_cookie) +{ + unsigned int parameters[1]; + parameters[0] = (unsigned int) seed_cookie; + return (bolos_bool_t) SVC_Call(SYSCALL_os_perso_seed_cookie_ID, parameters); } +#endif // HAVE_SEED_COOKIE -bolos_bool_t os_global_pin_check ( unsigned char * pin_buffer, unsigned char pin_length ) { - unsigned int parameters[2]; - parameters[0] = (unsigned int)pin_buffer; - parameters[1] = (unsigned int)pin_length; - return (bolos_bool_t) SVC_Call(SYSCALL_os_global_pin_check_ID, parameters); +unsigned int os_endorsement_get_code_hash(unsigned char *buffer) +{ + unsigned int parameters[2]; + parameters[0] = (unsigned int) buffer; + parameters[1] = 0; + return (unsigned int) SVC_Call(SYSCALL_os_endorsement_get_code_hash_ID, parameters); } -void os_global_pin_invalidate ( void ) { - unsigned int parameters[2]; - parameters[1] = 0; - SVC_Call(SYSCALL_os_global_pin_invalidate_ID, parameters); - return; +unsigned int os_endorsement_get_public_key(unsigned char index, + unsigned char *buffer, + unsigned char *length) +{ + unsigned int parameters[3]; + parameters[0] = (unsigned int) index; + parameters[1] = (unsigned int) buffer; + parameters[2] = (unsigned int) length; + return (unsigned int) SVC_Call(SYSCALL_os_endorsement_get_public_key_ID, parameters); } -unsigned int os_global_pin_retries ( void ) { - unsigned int parameters[2]; - parameters[1] = 0; - return (unsigned int) SVC_Call(SYSCALL_os_global_pin_retries_ID, parameters); +unsigned int os_endorsement_get_public_key_certificate(unsigned char index, + unsigned char *buffer, + unsigned char *length) +{ + unsigned int parameters[3]; + parameters[0] = (unsigned int) index; + parameters[1] = (unsigned int) buffer; + parameters[2] = (unsigned int) length; + return (unsigned int) SVC_Call(SYSCALL_os_endorsement_get_public_key_certificate_ID, + parameters); } -unsigned int os_registry_count ( void ) { - unsigned int parameters[2]; - parameters[1] = 0; - return (unsigned int) SVC_Call(SYSCALL_os_registry_count_ID, parameters); +unsigned int os_endorsement_key1_get_app_secret(unsigned char *buffer) +{ + unsigned int parameters[2]; + parameters[0] = (unsigned int) buffer; + parameters[1] = 0; + return (unsigned int) SVC_Call(SYSCALL_os_endorsement_key1_get_app_secret_ID, parameters); } -void os_registry_get ( unsigned int app_idx, application_t * out_application_entry ) { - unsigned int parameters[2]; - parameters[0] = (unsigned int)app_idx; - parameters[1] = (unsigned int)out_application_entry; - SVC_Call(SYSCALL_os_registry_get_ID, parameters); - return; +unsigned int os_endorsement_key1_sign_data(unsigned char *src, + unsigned int srcLength, + unsigned char *signature) +{ + unsigned int parameters[3]; + parameters[0] = (unsigned int) src; + parameters[1] = (unsigned int) srcLength; + parameters[2] = (unsigned int) signature; + return (unsigned int) SVC_Call(SYSCALL_os_endorsement_key1_sign_data_ID, parameters); } -#if !defined(APP_UX) -unsigned int os_ux ( bolos_ux_params_t * params ) { - unsigned int parameters[2]; - parameters[0] = (unsigned int)params; - parameters[1] = 0; - return (unsigned int) SVC_Call(SYSCALL_os_ux_ID, parameters); +unsigned int os_endorsement_key2_derive_sign_data(unsigned char *src, + unsigned int srcLength, + unsigned char *signature) +{ + unsigned int parameters[3]; + parameters[0] = (unsigned int) src; + parameters[1] = (unsigned int) srcLength; + parameters[2] = (unsigned int) signature; + return (unsigned int) SVC_Call(SYSCALL_os_endorsement_key2_derive_sign_data_ID, parameters); } -#endif // !defined(APP_UX) -void os_lib_call ( unsigned int * call_parameters ) { - unsigned int parameters[2]; - parameters[0] = (unsigned int)call_parameters; - parameters[1] = 0; - SVC_Call(SYSCALL_os_lib_call_ID, parameters); - return; +void os_perso_set_pin(unsigned int identity, + const unsigned char *pin, + unsigned int length, + bool update_crc) +{ + unsigned int parameters[4]; + parameters[0] = (unsigned int) identity; + parameters[1] = (unsigned int) pin; + parameters[2] = (unsigned int) length; + parameters[3] = (unsigned int) update_crc; + SVC_Call(SYSCALL_os_perso_set_pin_ID, parameters); + return; } -void __attribute__((noreturn)) os_lib_end ( void ) { - unsigned int parameters[2]; - parameters[1] = 0; - SVC_Call(SYSCALL_os_lib_end_ID, parameters); +void os_perso_set_current_identity_pin(unsigned char *pin, unsigned int length) +{ + unsigned int parameters[2]; + parameters[0] = (unsigned int) pin; + parameters[1] = (unsigned int) length; + SVC_Call(SYSCALL_os_perso_set_current_identity_pin_ID, parameters); + return; +} - // The os_lib_end syscall should never return. - // Just in case, crash the device thanks to an undefined instruction. - // To avoid the __builtin_unreachable undefined behaviour - asm volatile ("udf #255"); +bolos_bool_t os_perso_is_pin_set(void) +{ + unsigned int parameters[2]; + parameters[1] = 0; + return (bolos_bool_t) SVC_Call(SYSCALL_os_perso_is_pin_set_ID, parameters); +} - // remove the warning caused by -Winvalid-noreturn - __builtin_unreachable(); +bolos_bool_t os_global_pin_is_validated(void) +{ + unsigned int parameters[2]; + parameters[1] = 0; + return (bolos_bool_t) SVC_Call(SYSCALL_os_global_pin_is_validated_ID, parameters); } -unsigned int os_flags ( void ) { - unsigned int parameters[2]; - parameters[1] = 0; - return (unsigned int) SVC_Call(SYSCALL_os_flags_ID, parameters); +bolos_bool_t os_global_pin_check(unsigned char *pin_buffer, unsigned char pin_length) +{ + unsigned int parameters[2]; + parameters[0] = (unsigned int) pin_buffer; + parameters[1] = (unsigned int) pin_length; + return (bolos_bool_t) SVC_Call(SYSCALL_os_global_pin_check_ID, parameters); } -unsigned int os_version ( unsigned char * version, unsigned int maxlength ) { - unsigned int parameters[2]; - parameters[0] = (unsigned int)version; - parameters[1] = (unsigned int)maxlength; - return (unsigned int) SVC_Call(SYSCALL_os_version_ID, parameters); +void os_global_pin_invalidate(void) +{ + unsigned int parameters[2]; + parameters[1] = 0; + SVC_Call(SYSCALL_os_global_pin_invalidate_ID, parameters); + return; } -unsigned int os_serial ( unsigned char * serial, unsigned int maxlength ) { - unsigned int parameters[2]; - parameters[0] = (unsigned int)serial; - parameters[1] = (unsigned int)maxlength; - return (unsigned int) SVC_Call(SYSCALL_os_serial_ID, parameters); +unsigned int os_global_pin_retries(void) +{ + unsigned int parameters[2]; + parameters[1] = 0; + return (unsigned int) SVC_Call(SYSCALL_os_global_pin_retries_ID, parameters); } -unsigned int os_seph_features ( void ) { - unsigned int parameters[2]; - parameters[1] = 0; - return (unsigned int) SVC_Call(SYSCALL_os_seph_features_ID, parameters); +unsigned int os_registry_count(void) +{ + unsigned int parameters[2]; + parameters[1] = 0; + return (unsigned int) SVC_Call(SYSCALL_os_registry_count_ID, parameters); } -unsigned int os_seph_version ( unsigned char * version, unsigned int maxlength ) { - unsigned int parameters[2]; - parameters[0] = (unsigned int)version; - parameters[1] = (unsigned int)maxlength; - return (unsigned int) SVC_Call(SYSCALL_os_seph_version_ID, parameters); +void os_registry_get(unsigned int app_idx, application_t *out_application_entry) +{ + unsigned int parameters[2]; + parameters[0] = (unsigned int) app_idx; + parameters[1] = (unsigned int) out_application_entry; + SVC_Call(SYSCALL_os_registry_get_ID, parameters); + return; } -unsigned int os_bootloader_version ( unsigned char * version, unsigned int maxlength ) { - unsigned int parameters[2]; - parameters[0] = (unsigned int)version; - parameters[1] = (unsigned int)maxlength; - return (unsigned int) SVC_Call(SYSCALL_os_bootloader_version_ID, parameters); +#if !defined(APP_UX) +unsigned int os_ux(bolos_ux_params_t *params) +{ + unsigned int parameters[2]; + parameters[0] = (unsigned int) params; + parameters[1] = 0; + return (unsigned int) SVC_Call(SYSCALL_os_ux_ID, parameters); } +#endif // !defined(APP_UX) -unsigned int os_factory_setting_get ( unsigned int id, unsigned char * value, unsigned int maxlength ) { - unsigned int parameters[3]; - parameters[0] = (unsigned int)id; - parameters[1] = (unsigned int)value; - parameters[2] = (unsigned int)maxlength; - return (unsigned int) SVC_Call(SYSCALL_os_factory_setting_get_ID, parameters); +void os_lib_call(unsigned int *call_parameters) +{ + unsigned int parameters[2]; + parameters[0] = (unsigned int) call_parameters; + parameters[1] = 0; + SVC_Call(SYSCALL_os_lib_call_ID, parameters); + return; } -unsigned int os_setting_get ( unsigned int setting_id, unsigned char * value, unsigned int maxlen ) { - unsigned int parameters[3]; - parameters[0] = (unsigned int)setting_id; - parameters[1] = (unsigned int)value; - parameters[2] = (unsigned int)maxlen; - return (unsigned int) SVC_Call(SYSCALL_os_setting_get_ID, parameters); +void __attribute__((noreturn)) os_lib_end(void) +{ + unsigned int parameters[2]; + parameters[1] = 0; + SVC_Call(SYSCALL_os_lib_end_ID, parameters); + + // The os_lib_end syscall should never return. + // Just in case, crash the device thanks to an undefined instruction. + // To avoid the __builtin_unreachable undefined behaviour + asm volatile("udf #255"); + + // remove the warning caused by -Winvalid-noreturn + __builtin_unreachable(); } -void os_setting_set ( unsigned int setting_id, unsigned char * value, unsigned int length ) { - unsigned int parameters[3]; - parameters[0] = (unsigned int)setting_id; - parameters[1] = (unsigned int)value; - parameters[2] = (unsigned int)length; - SVC_Call(SYSCALL_os_setting_set_ID, parameters); - return; +unsigned int os_flags(void) +{ + unsigned int parameters[2]; + parameters[1] = 0; + return (unsigned int) SVC_Call(SYSCALL_os_flags_ID, parameters); } -void os_get_memory_info ( meminfo_t * meminfo ) { - unsigned int parameters[2]; - parameters[0] = (unsigned int)meminfo; - parameters[1] = 0; - SVC_Call(SYSCALL_os_get_memory_info_ID, parameters); - return; +unsigned int os_version(unsigned char *version, unsigned int maxlength) +{ + unsigned int parameters[2]; + parameters[0] = (unsigned int) version; + parameters[1] = (unsigned int) maxlength; + return (unsigned int) SVC_Call(SYSCALL_os_version_ID, parameters); } -unsigned int os_registry_get_tag ( unsigned int app_idx, unsigned int * tlvoffset, unsigned int tag, unsigned int value_offset, void * buffer, unsigned int maxlength ) { - unsigned int parameters[6]; - parameters[0] = (unsigned int)app_idx; - parameters[1] = (unsigned int)tlvoffset; - parameters[2] = (unsigned int)tag; - parameters[3] = (unsigned int)value_offset; - parameters[4] = (unsigned int)buffer; - parameters[5] = (unsigned int)maxlength; - return (unsigned int) SVC_Call(SYSCALL_os_registry_get_tag_ID, parameters); +unsigned int os_serial(unsigned char *serial, unsigned int maxlength) +{ + unsigned int parameters[2]; + parameters[0] = (unsigned int) serial; + parameters[1] = (unsigned int) maxlength; + return (unsigned int) SVC_Call(SYSCALL_os_serial_ID, parameters); } -unsigned int os_registry_get_current_app_tag ( unsigned int tag, unsigned char * buffer, unsigned int maxlen ) { - unsigned int parameters[3]; - parameters[0] = (unsigned int)tag; - parameters[1] = (unsigned int)buffer; - parameters[2] = (unsigned int)maxlen; - return (unsigned int) SVC_Call(SYSCALL_os_registry_get_current_app_tag_ID, parameters); +unsigned int os_seph_features(void) +{ + unsigned int parameters[2]; + parameters[1] = 0; + return (unsigned int) SVC_Call(SYSCALL_os_seph_features_ID, parameters); } -void os_registry_delete_app_and_dependees ( unsigned int app_idx ) { - unsigned int parameters[2]; - parameters[0] = (unsigned int)app_idx; - parameters[1] = 0; - SVC_Call(SYSCALL_os_registry_delete_app_and_dependees_ID, parameters); - return; +unsigned int os_seph_version(unsigned char *version, unsigned int maxlength) +{ + unsigned int parameters[2]; + parameters[0] = (unsigned int) version; + parameters[1] = (unsigned int) maxlength; + return (unsigned int) SVC_Call(SYSCALL_os_seph_version_ID, parameters); } -void os_registry_delete_all_apps ( void ) { - unsigned int parameters[2]; - parameters[1] = 0; - SVC_Call(SYSCALL_os_registry_delete_all_apps_ID, parameters); - return; +unsigned int os_bootloader_version(unsigned char *version, unsigned int maxlength) +{ + unsigned int parameters[2]; + parameters[0] = (unsigned int) version; + parameters[1] = (unsigned int) maxlength; + return (unsigned int) SVC_Call(SYSCALL_os_bootloader_version_ID, parameters); } -#ifndef HAVE_BOLOS_NO_CUSTOMCA -unsigned int os_customca_verify ( unsigned char * hash, unsigned char * sign, unsigned int sign_length ) { - unsigned int parameters[3]; - parameters[0] = (unsigned int)hash; - parameters[1] = (unsigned int)sign; - parameters[2] = (unsigned int)sign_length; - return (unsigned int) SVC_Call(SYSCALL_os_customca_verify_ID, parameters); +unsigned int os_factory_setting_get(unsigned int id, unsigned char *value, unsigned int maxlength) +{ + unsigned int parameters[3]; + parameters[0] = (unsigned int) id; + parameters[1] = (unsigned int) value; + parameters[2] = (unsigned int) maxlength; + return (unsigned int) SVC_Call(SYSCALL_os_factory_setting_get_ID, parameters); } -#endif // HAVE_BOLOS_NO_CUSTOMCA -void os_sched_exec ( unsigned int app_idx ) { - unsigned int parameters[2]; - parameters[0] = (unsigned int)app_idx; - parameters[1] = 0; - SVC_Call(SYSCALL_os_sched_exec_ID, parameters); - return; +unsigned int os_setting_get(unsigned int setting_id, unsigned char *value, unsigned int maxlen) +{ + unsigned int parameters[3]; + parameters[0] = (unsigned int) setting_id; + parameters[1] = (unsigned int) value; + parameters[2] = (unsigned int) maxlen; + return (unsigned int) SVC_Call(SYSCALL_os_setting_get_ID, parameters); } -void __attribute__((noreturn)) os_sched_exit ( bolos_task_status_t exit_code ) { - unsigned int parameters[2]; - parameters[0] = (unsigned int)exit_code; - parameters[1] = 0; - SVC_Call(SYSCALL_os_sched_exit_ID, parameters); +void os_setting_set(unsigned int setting_id, unsigned char *value, unsigned int length) +{ + unsigned int parameters[3]; + parameters[0] = (unsigned int) setting_id; + parameters[1] = (unsigned int) value; + parameters[2] = (unsigned int) length; + SVC_Call(SYSCALL_os_setting_set_ID, parameters); + return; +} - // The os_sched_exit syscall should never return. - // Just in case, crash the device thanks to an undefined instruction. - // To avoid the __builtin_unreachable undefined behaviour - asm volatile ("udf #255"); +void os_get_memory_info(meminfo_t *meminfo) +{ + unsigned int parameters[2]; + parameters[0] = (unsigned int) meminfo; + parameters[1] = 0; + SVC_Call(SYSCALL_os_get_memory_info_ID, parameters); + return; +} + +unsigned int os_registry_get_tag(unsigned int app_idx, + unsigned int *tlvoffset, + unsigned int tag, + unsigned int value_offset, + void *buffer, + unsigned int maxlength) +{ + unsigned int parameters[6]; + parameters[0] = (unsigned int) app_idx; + parameters[1] = (unsigned int) tlvoffset; + parameters[2] = (unsigned int) tag; + parameters[3] = (unsigned int) value_offset; + parameters[4] = (unsigned int) buffer; + parameters[5] = (unsigned int) maxlength; + return (unsigned int) SVC_Call(SYSCALL_os_registry_get_tag_ID, parameters); +} + +unsigned int os_registry_get_current_app_tag(unsigned int tag, + unsigned char *buffer, + unsigned int maxlen) +{ + unsigned int parameters[3]; + parameters[0] = (unsigned int) tag; + parameters[1] = (unsigned int) buffer; + parameters[2] = (unsigned int) maxlen; + return (unsigned int) SVC_Call(SYSCALL_os_registry_get_current_app_tag_ID, parameters); +} - // remove the warning caused by -Winvalid-noreturn - __builtin_unreachable(); +void os_registry_delete_app_and_dependees(unsigned int app_idx) +{ + unsigned int parameters[2]; + parameters[0] = (unsigned int) app_idx; + parameters[1] = 0; + SVC_Call(SYSCALL_os_registry_delete_app_and_dependees_ID, parameters); + return; } -bolos_bool_t os_sched_is_running ( unsigned int task_idx ) { - unsigned int parameters[2]; - parameters[0] = (unsigned int)task_idx; - parameters[1] = 0; - return (bolos_bool_t) SVC_Call(SYSCALL_os_sched_is_running_ID, parameters); +void os_registry_delete_all_apps(void) +{ + unsigned int parameters[2]; + parameters[1] = 0; + SVC_Call(SYSCALL_os_registry_delete_all_apps_ID, parameters); + return; } -unsigned int os_sched_create ( void * main, void * nvram, unsigned int nvram_length, void * ram0, unsigned int ram0_length, void * stack, unsigned int stack_length ) { - unsigned int parameters[7]; - parameters[0] = (unsigned int)main; - parameters[1] = (unsigned int)nvram; - parameters[2] = (unsigned int)nvram_length; - parameters[3] = (unsigned int)ram0; - parameters[4] = (unsigned int)ram0_length; - parameters[5] = (unsigned int)stack; - parameters[6] = (unsigned int)stack_length; - return (unsigned int) SVC_Call(SYSCALL_os_sched_create_ID, parameters); +#ifndef HAVE_BOLOS_NO_CUSTOMCA +unsigned int os_customca_verify(unsigned char *hash, unsigned char *sign, unsigned int sign_length) +{ + unsigned int parameters[3]; + parameters[0] = (unsigned int) hash; + parameters[1] = (unsigned int) sign; + parameters[2] = (unsigned int) sign_length; + return (unsigned int) SVC_Call(SYSCALL_os_customca_verify_ID, parameters); } +#endif // HAVE_BOLOS_NO_CUSTOMCA -void os_sched_kill ( unsigned int taskidx ) { - unsigned int parameters[2]; - parameters[0] = (unsigned int)taskidx; - parameters[1] = 0; - SVC_Call(SYSCALL_os_sched_kill_ID, parameters); - return; +void os_sched_exec(unsigned int app_idx) +{ + unsigned int parameters[2]; + parameters[0] = (unsigned int) app_idx; + parameters[1] = 0; + SVC_Call(SYSCALL_os_sched_exec_ID, parameters); + return; } -void io_seph_send ( const unsigned char * buffer, unsigned short length ) { - unsigned int parameters[2]; - parameters[0] = (unsigned int)buffer; - parameters[1] = (unsigned int)length; - SVC_Call(SYSCALL_io_seph_send_ID, parameters); - return; +void __attribute__((noreturn)) os_sched_exit(bolos_task_status_t exit_code) +{ + unsigned int parameters[2]; + parameters[0] = (unsigned int) exit_code; + parameters[1] = 0; + SVC_Call(SYSCALL_os_sched_exit_ID, parameters); + + // The os_sched_exit syscall should never return. + // Just in case, crash the device thanks to an undefined instruction. + // To avoid the __builtin_unreachable undefined behaviour + asm volatile("udf #255"); + + // remove the warning caused by -Winvalid-noreturn + __builtin_unreachable(); } -unsigned int io_seph_is_status_sent ( void ) { - unsigned int parameters[2]; - parameters[1] = 0; - return (unsigned int) SVC_Call(SYSCALL_io_seph_is_status_sent_ID, parameters); +bolos_bool_t os_sched_is_running(unsigned int task_idx) +{ + unsigned int parameters[2]; + parameters[0] = (unsigned int) task_idx; + parameters[1] = 0; + return (bolos_bool_t) SVC_Call(SYSCALL_os_sched_is_running_ID, parameters); +} + +unsigned int os_sched_create(void *main, + void *nvram, + unsigned int nvram_length, + void *ram0, + unsigned int ram0_length, + void *stack, + unsigned int stack_length) +{ + unsigned int parameters[7]; + parameters[0] = (unsigned int) main; + parameters[1] = (unsigned int) nvram; + parameters[2] = (unsigned int) nvram_length; + parameters[3] = (unsigned int) ram0; + parameters[4] = (unsigned int) ram0_length; + parameters[5] = (unsigned int) stack; + parameters[6] = (unsigned int) stack_length; + return (unsigned int) SVC_Call(SYSCALL_os_sched_create_ID, parameters); +} + +void os_sched_kill(unsigned int taskidx) +{ + unsigned int parameters[2]; + parameters[0] = (unsigned int) taskidx; + parameters[1] = 0; + SVC_Call(SYSCALL_os_sched_kill_ID, parameters); + return; } -unsigned short io_seph_recv ( unsigned char * buffer, unsigned short maxlength, unsigned int flags ) { - unsigned int parameters[3]; - parameters[0] = (unsigned int)buffer; - parameters[1] = (unsigned int)maxlength; - parameters[2] = (unsigned int)flags; - return (unsigned short) SVC_Call(SYSCALL_io_seph_recv_ID, parameters); +void io_seph_send(const unsigned char *buffer, unsigned short length) +{ + unsigned int parameters[2]; + parameters[0] = (unsigned int) buffer; + parameters[1] = (unsigned int) length; + SVC_Call(SYSCALL_io_seph_send_ID, parameters); + return; +} + +unsigned int io_seph_is_status_sent(void) +{ + unsigned int parameters[2]; + parameters[1] = 0; + return (unsigned int) SVC_Call(SYSCALL_io_seph_is_status_sent_ID, parameters); +} + +unsigned short io_seph_recv(unsigned char *buffer, unsigned short maxlength, unsigned int flags) +{ + unsigned int parameters[3]; + parameters[0] = (unsigned int) buffer; + parameters[1] = (unsigned int) maxlength; + parameters[2] = (unsigned int) flags; + return (unsigned short) SVC_Call(SYSCALL_io_seph_recv_ID, parameters); } -void nvm_write_page(unsigned int page_adr, bool force) { - unsigned int parameters[2]; - parameters[0] = (unsigned int) page_adr; - parameters[1] = (unsigned int) force; - SVC_Call(SYSCALL_nvm_write_page_ID, parameters); - return; +void nvm_write_page(unsigned int page_adr, bool force) +{ + unsigned int parameters[2]; + parameters[0] = (unsigned int) page_adr; + parameters[1] = (unsigned int) force; + SVC_Call(SYSCALL_nvm_write_page_ID, parameters); + return; } -void nvm_erase_page ( unsigned int page_adr ) { - unsigned int parameters[2]; - parameters[0] = (unsigned int)page_adr; - parameters[1] = 0; - SVC_Call(SYSCALL_nvm_erase_page_ID, parameters); - return; +void nvm_erase_page(unsigned int page_adr) +{ + unsigned int parameters[2]; + parameters[0] = (unsigned int) page_adr; + parameters[1] = 0; + SVC_Call(SYSCALL_nvm_erase_page_ID, parameters); + return; } -try_context_t * try_context_get ( void ) { - unsigned int parameters[2]; - parameters[1] = 0; - return (try_context_t *) SVC_Call(SYSCALL_try_context_get_ID, parameters); +try_context_t *try_context_get(void) +{ + unsigned int parameters[2]; + parameters[1] = 0; + return (try_context_t *) SVC_Call(SYSCALL_try_context_get_ID, parameters); } -try_context_t * try_context_set ( try_context_t *context ) { - unsigned int parameters[2]; - parameters[0] = (unsigned int)context; - parameters[1] = 0; - return (try_context_t *) SVC_Call(SYSCALL_try_context_set_ID, parameters); +try_context_t *try_context_set(try_context_t *context) +{ + unsigned int parameters[2]; + parameters[0] = (unsigned int) context; + parameters[1] = 0; + return (try_context_t *) SVC_Call(SYSCALL_try_context_set_ID, parameters); } -bolos_task_status_t os_sched_last_status ( unsigned int task_idx ) { - unsigned int parameters[2]; - parameters[0] = (unsigned int)task_idx; - parameters[1] = 0; - return (bolos_task_status_t) SVC_Call(SYSCALL_os_sched_last_status_ID, parameters); +bolos_task_status_t os_sched_last_status(unsigned int task_idx) +{ + unsigned int parameters[2]; + parameters[0] = (unsigned int) task_idx; + parameters[1] = 0; + return (bolos_task_status_t) SVC_Call(SYSCALL_os_sched_last_status_ID, parameters); } -void os_sched_yield ( bolos_task_status_t status ) { - unsigned int parameters[2]; - parameters[0] = (unsigned int)status; - parameters[1] = 0; - SVC_Call(SYSCALL_os_sched_yield_ID, parameters); - return; +void os_sched_yield(bolos_task_status_t status) +{ + unsigned int parameters[2]; + parameters[0] = (unsigned int) status; + parameters[1] = 0; + SVC_Call(SYSCALL_os_sched_yield_ID, parameters); + return; } -void os_sched_switch ( unsigned int task_idx, bolos_task_status_t status ) { - unsigned int parameters[2]; - parameters[0] = (unsigned int)task_idx; - parameters[1] = (unsigned int)status; - SVC_Call(SYSCALL_os_sched_switch_ID, parameters); - return; +void os_sched_switch(unsigned int task_idx, bolos_task_status_t status) +{ + unsigned int parameters[2]; + parameters[0] = (unsigned int) task_idx; + parameters[1] = (unsigned int) status; + SVC_Call(SYSCALL_os_sched_switch_ID, parameters); + return; } -unsigned int os_sched_current_task ( void ) { - unsigned int parameters[2]; - parameters[1] = 0; - return (unsigned int) SVC_Call(SYSCALL_os_sched_current_task_ID, parameters); +unsigned int os_sched_current_task(void) +{ + unsigned int parameters[2]; + parameters[1] = 0; + return (unsigned int) SVC_Call(SYSCALL_os_sched_current_task_ID, parameters); } -unsigned int os_allow_protected_ram( void ) { - unsigned int parameters[2]; - parameters[1] = 0; - return (unsigned int) SVC_Call(SYSCALL_os_allow_protected_ram_ID, parameters); +unsigned int os_allow_protected_ram(void) +{ + unsigned int parameters[2]; + parameters[1] = 0; + return (unsigned int) SVC_Call(SYSCALL_os_allow_protected_ram_ID, parameters); } -unsigned int os_deny_protected_ram( void ) { - unsigned int parameters[2]; - parameters[1] = 0; - return (unsigned int) SVC_Call(SYSCALL_os_deny_protected_ram_ID, parameters); +unsigned int os_deny_protected_ram(void) +{ + unsigned int parameters[2]; + parameters[1] = 0; + return (unsigned int) SVC_Call(SYSCALL_os_deny_protected_ram_ID, parameters); } -unsigned int os_allow_protected_flash( void ) { - unsigned int parameters[2]; - parameters[1] = 0; - return (unsigned int) SVC_Call(SYSCALL_os_allow_protected_flash_ID, parameters); +unsigned int os_allow_protected_flash(void) +{ + unsigned int parameters[2]; + parameters[1] = 0; + return (unsigned int) SVC_Call(SYSCALL_os_allow_protected_flash_ID, parameters); } -unsigned int os_deny_protected_flash( void ) { - unsigned int parameters[2]; - parameters[1] = 0; - return (unsigned int) SVC_Call(SYSCALL_os_deny_protected_flash_ID, parameters); +unsigned int os_deny_protected_flash(void) +{ + unsigned int parameters[2]; + parameters[1] = 0; + return (unsigned int) SVC_Call(SYSCALL_os_deny_protected_flash_ID, parameters); } #ifdef HAVE_CUSTOM_CA_DETAILS_IN_SETTINGS -bolos_bool_t os_bolos_custom_ca_get_info(customca_data_t *custom_ca) { - unsigned int parameters[2]; - parameters[0] = (unsigned int) custom_ca; - bolos_bool_t ret = (bolos_bool_t) SVC_Call(SYSCALL_os_bolos_custom_ca_get_info_ID, parameters); - return ret; +bolos_bool_t os_bolos_custom_ca_get_info(customca_data_t *custom_ca) +{ + unsigned int parameters[2]; + parameters[0] = (unsigned int) custom_ca; + bolos_bool_t ret = (bolos_bool_t) SVC_Call(SYSCALL_os_bolos_custom_ca_get_info_ID, parameters); + return ret; } -void os_bolos_custom_ca_revoke(void) { - unsigned int parameters[1]; - parameters[0] = 0; - SVC_Call(SYSCALL_os_bolos_custom_ca_revoke_ID, parameters); - return; +void os_bolos_custom_ca_revoke(void) +{ + unsigned int parameters[1]; + parameters[0] = 0; + SVC_Call(SYSCALL_os_bolos_custom_ca_revoke_ID, parameters); + return; } -#endif //HAVE_CUSTOM_CA_DETAILS_IN_SETTINGS +#endif // HAVE_CUSTOM_CA_DETAILS_IN_SETTINGS -bolos_bool_t os_bolos_endorsement_revoke(uint8_t slot) { - unsigned int parameters[1]; - parameters[0] = (unsigned int) slot; - bolos_bool_t ret = SVC_Call(SYSCALL_os_bolos_endorsement_revoke_ID, parameters); - return ret; +bolos_bool_t os_bolos_endorsement_revoke(uint8_t slot) +{ + unsigned int parameters[1]; + parameters[0] = (unsigned int) slot; + bolos_bool_t ret = SVC_Call(SYSCALL_os_bolos_endorsement_revoke_ID, parameters); + return ret; } #ifdef HAVE_MCU_SERIAL_STORAGE -unsigned int os_seph_serial ( unsigned char * serial, unsigned int maxlength ) { - unsigned int parameters[2]; - parameters[0] = (unsigned int)serial; - parameters[1] = (unsigned int)maxlength; - return (unsigned int) SVC_Call(SYSCALL_os_seph_serial_ID, parameters); +unsigned int os_seph_serial(unsigned char *serial, unsigned int maxlength) +{ + unsigned int parameters[2]; + parameters[0] = (unsigned int) serial; + parameters[1] = (unsigned int) maxlength; + return (unsigned int) SVC_Call(SYSCALL_os_seph_serial_ID, parameters); } #endif #ifdef HAVE_SE_SCREEN -void screen_clear ( void ) { - unsigned int parameters[2]; - parameters[1] = 0; - SVC_Call(SYSCALL_screen_clear_ID, parameters); - return; +void screen_clear(void) +{ + unsigned int parameters[2]; + parameters[1] = 0; + SVC_Call(SYSCALL_screen_clear_ID, parameters); + return; } -void screen_update ( void ) { - unsigned int parameters[2]; - parameters[1] = 0; - SVC_Call(SYSCALL_screen_update_ID, parameters); - return; +void screen_update(void) +{ + unsigned int parameters[2]; + parameters[1] = 0; + SVC_Call(SYSCALL_screen_update_ID, parameters); + return; } #ifdef HAVE_BRIGHTNESS_SYSCALL -void screen_set_brightness ( unsigned int percent ) { - unsigned int parameters[2]; - parameters[0] = (unsigned int)percent; - SVC_Call(SYSCALL_screen_set_brightness_ID, parameters); - return; -} -#endif // HAVE_BRIGHTNESS_SYSCALL - -void screen_set_keepout ( unsigned int x, unsigned int y, unsigned int width, unsigned int height ) { - unsigned int parameters[4]; - parameters[0] = (unsigned int)x; - parameters[1] = (unsigned int)y; - parameters[2] = (unsigned int)width; - parameters[3] = (unsigned int)height; - SVC_Call(SYSCALL_screen_set_keepout_ID, parameters); - return; -} - -void bagl_hal_draw_bitmap_within_rect ( int x, int y, unsigned int width, unsigned int height, unsigned int color_count, const unsigned int * colors, unsigned int bit_per_pixel, const unsigned char * bitmap, unsigned int bitmap_length_bits ) { - unsigned int parameters[9]; - parameters[0] = (unsigned int)x; - parameters[1] = (unsigned int)y; - parameters[2] = (unsigned int)width; - parameters[3] = (unsigned int)height; - parameters[4] = (unsigned int)color_count; - parameters[5] = (unsigned int)colors; - parameters[6] = (unsigned int)bit_per_pixel; - parameters[7] = (unsigned int)bitmap; - parameters[8] = (unsigned int)bitmap_length_bits; - SVC_Call(SYSCALL_bagl_hal_draw_bitmap_within_rect_ID, parameters); - return; -} - -void bagl_hal_draw_rect ( unsigned int color, int x, int y, unsigned int width, unsigned int height ) { - unsigned int parameters[5]; - parameters[0] = (unsigned int)color; - parameters[1] = (unsigned int)x; - parameters[2] = (unsigned int)y; - parameters[3] = (unsigned int)width; - parameters[4] = (unsigned int)height; - SVC_Call(SYSCALL_bagl_hal_draw_rect_ID, parameters); - return; +void screen_set_brightness(unsigned int percent) +{ + unsigned int parameters[2]; + parameters[0] = (unsigned int) percent; + SVC_Call(SYSCALL_screen_set_brightness_ID, parameters); + return; +} +#endif // HAVE_BRIGHTNESS_SYSCALL + +void screen_set_keepout(unsigned int x, unsigned int y, unsigned int width, unsigned int height) +{ + unsigned int parameters[4]; + parameters[0] = (unsigned int) x; + parameters[1] = (unsigned int) y; + parameters[2] = (unsigned int) width; + parameters[3] = (unsigned int) height; + SVC_Call(SYSCALL_screen_set_keepout_ID, parameters); + return; +} + +void bagl_hal_draw_bitmap_within_rect(int x, + int y, + unsigned int width, + unsigned int height, + unsigned int color_count, + const unsigned int *colors, + unsigned int bit_per_pixel, + const unsigned char *bitmap, + unsigned int bitmap_length_bits) +{ + unsigned int parameters[9]; + parameters[0] = (unsigned int) x; + parameters[1] = (unsigned int) y; + parameters[2] = (unsigned int) width; + parameters[3] = (unsigned int) height; + parameters[4] = (unsigned int) color_count; + parameters[5] = (unsigned int) colors; + parameters[6] = (unsigned int) bit_per_pixel; + parameters[7] = (unsigned int) bitmap; + parameters[8] = (unsigned int) bitmap_length_bits; + SVC_Call(SYSCALL_bagl_hal_draw_bitmap_within_rect_ID, parameters); + return; +} + +void bagl_hal_draw_rect(unsigned int color, int x, int y, unsigned int width, unsigned int height) +{ + unsigned int parameters[5]; + parameters[0] = (unsigned int) color; + parameters[1] = (unsigned int) x; + parameters[2] = (unsigned int) y; + parameters[3] = (unsigned int) width; + parameters[4] = (unsigned int) height; + SVC_Call(SYSCALL_bagl_hal_draw_rect_ID, parameters); + return; } #endif #ifdef HAVE_BLE -void os_ux_set_status ( unsigned int ux_id, unsigned int status ) { - unsigned int parameters [2+2]; - parameters[0] = (unsigned int)ux_id; - parameters[1] = (unsigned int)status; - SVC_Call(SYSCALL_os_ux_set_status_ID_IN, parameters); - return; +void os_ux_set_status(unsigned int ux_id, unsigned int status) +{ + unsigned int parameters[2 + 2]; + parameters[0] = (unsigned int) ux_id; + parameters[1] = (unsigned int) status; + SVC_Call(SYSCALL_os_ux_set_status_ID_IN, parameters); + return; } -unsigned int os_ux_get_status ( unsigned int ux_id ) { - unsigned int parameters [2+1]; - parameters[0] = (unsigned int)ux_id; - parameters[1] = 0; - return (unsigned int) SVC_Call(SYSCALL_os_ux_get_status_ID_IN, parameters); +unsigned int os_ux_get_status(unsigned int ux_id) +{ + unsigned int parameters[2 + 1]; + parameters[0] = (unsigned int) ux_id; + parameters[1] = 0; + return (unsigned int) SVC_Call(SYSCALL_os_ux_get_status_ID_IN, parameters); } -#endif // HAVE_BLE +#endif // HAVE_BLE #ifdef HAVE_SE_BUTTON -unsigned int io_button_read ( void ) { - unsigned int parameters[2]; - parameters[1] = 0; - return (unsigned int) SVC_Call(SYSCALL_io_button_read_ID, parameters); +unsigned int io_button_read(void) +{ + unsigned int parameters[2]; + parameters[1] = 0; + return (unsigned int) SVC_Call(SYSCALL_io_button_read_ID, parameters); } -#endif // HAVE_SE_BUTTON +#endif // HAVE_SE_BUTTON #ifdef HAVE_AEM_PIN -void os_aem_set_pin ( unsigned char * aem_pin, unsigned int aem_pin_length ) { - unsigned int parameters[2]; - parameters[0] = (unsigned int)aem_pin; - parameters[1] = (unsigned int)aem_pin_length; - SVC_Call(SYSCALL_os_aem_set_pin_ID, parameters); - return; +void os_aem_set_pin(unsigned char *aem_pin, unsigned int aem_pin_length) +{ + unsigned int parameters[2]; + parameters[0] = (unsigned int) aem_pin; + parameters[1] = (unsigned int) aem_pin_length; + SVC_Call(SYSCALL_os_aem_set_pin_ID, parameters); + return; } -void os_aem_unset_pin ( void ) { - unsigned int parameters[2]; - parameters[1] = 0; - SVC_Call(SYSCALL_os_aem_unset_pin_ID, parameters); - return; +void os_aem_unset_pin(void) +{ + unsigned int parameters[2]; + parameters[1] = 0; + SVC_Call(SYSCALL_os_aem_unset_pin_ID, parameters); + return; } -bolos_bool_t os_aem_is_pin_set ( void ) { - unsigned int parameters[2]; - parameters[1] = 0; - return (bolos_bool_t) SVC_Call(SYSCALL_os_aem_is_pin_set_ID, parameters); +bolos_bool_t os_aem_is_pin_set(void) +{ + unsigned int parameters[2]; + parameters[1] = 0; + return (bolos_bool_t) SVC_Call(SYSCALL_os_aem_is_pin_set_ID, parameters); } -void os_aem_set_response ( unsigned char * aem_response, unsigned int aem_response_length, unsigned char aem_response_format ) { - unsigned int parameters[3]; - parameters[0] = (unsigned int)aem_response; - parameters[1] = (unsigned int)aem_response_length; - parameters[2] = (unsigned int)aem_response_format; - SVC_Call(SYSCALL_os_aem_set_response_ID, parameters); - return; +void os_aem_set_response(unsigned char *aem_response, + unsigned int aem_response_length, + unsigned char aem_response_format) +{ + unsigned int parameters[3]; + parameters[0] = (unsigned int) aem_response; + parameters[1] = (unsigned int) aem_response_length; + parameters[2] = (unsigned int) aem_response_format; + SVC_Call(SYSCALL_os_aem_set_response_ID, parameters); + return; } -void os_aem_activate_response ( void ) { - unsigned int parameters[2]; - parameters[1] = 0; - SVC_Call(SYSCALL_os_aem_activate_response_ID, parameters); - return; +void os_aem_activate_response(void) +{ + unsigned int parameters[2]; + parameters[1] = 0; + SVC_Call(SYSCALL_os_aem_activate_response_ID, parameters); + return; } -void os_aem_deactivate_response ( void ) { - unsigned int parameters[2]; - parameters[1] = 0; - SVC_Call(SYSCALL_os_aem_deactivate_response_ID, parameters); - return; +void os_aem_deactivate_response(void) +{ + unsigned int parameters[2]; + parameters[1] = 0; + SVC_Call(SYSCALL_os_aem_deactivate_response_ID, parameters); + return; } -bolos_bool_t os_aem_is_response_active ( void ) { - unsigned int parameters[2]; - parameters[1] = 0; - return (bolos_bool_t) SVC_Call(SYSCALL_os_aem_is_response_active_ID, parameters); +bolos_bool_t os_aem_is_response_active(void) +{ + unsigned int parameters[2]; + parameters[1] = 0; + return (bolos_bool_t) SVC_Call(SYSCALL_os_aem_is_response_active_ID, parameters); } -bolos_bool_t os_aem_is_feature_active ( void ) { - unsigned int parameters[2]; - parameters[1] = 0; - return (bolos_bool_t) SVC_Call(SYSCALL_os_aem_is_feature_active_ID, parameters); +bolos_bool_t os_aem_is_feature_active(void) +{ + unsigned int parameters[2]; + parameters[1] = 0; + return (bolos_bool_t) SVC_Call(SYSCALL_os_aem_is_feature_active_ID, parameters); } -unsigned char os_aem_get_response_length ( void ) { - unsigned int parameters[2]; - parameters[1] = 0; - return (unsigned char) SVC_Call(SYSCALL_os_aem_get_response_length_ID, parameters); +unsigned char os_aem_get_response_length(void) +{ + unsigned int parameters[2]; + parameters[1] = 0; + return (unsigned char) SVC_Call(SYSCALL_os_aem_get_response_length_ID, parameters); } -unsigned char os_aem_get_response_format ( void ) { - unsigned int parameters[2]; - parameters[1] = 0; - return (unsigned char) SVC_Call(SYSCALL_os_aem_get_response_format_ID, parameters); +unsigned char os_aem_get_response_format(void) +{ + unsigned int parameters[2]; + parameters[1] = 0; + return (unsigned char) SVC_Call(SYSCALL_os_aem_get_response_format_ID, parameters); } -void os_aem_get_response ( char * output_response_buffer, unsigned char input_required_length ) { - unsigned int parameters[2]; - parameters[0] = (unsigned int)output_response_buffer; - parameters[1] = (unsigned int)input_required_length; - SVC_Call(SYSCALL_os_aem_get_response_ID, parameters); - return; +void os_aem_get_response(char *output_response_buffer, unsigned char input_required_length) +{ + unsigned int parameters[2]; + parameters[0] = (unsigned int) output_response_buffer; + parameters[1] = (unsigned int) input_required_length; + SVC_Call(SYSCALL_os_aem_get_response_ID, parameters); + return; } -bolos_bool_t os_aem_check_pin ( unsigned char * aem_pin_buffer, unsigned char aem_pin_length ) { - unsigned int parameters[2]; - parameters[0] = (unsigned int)aem_pin_buffer; - parameters[1] = (unsigned int)aem_pin_length; - return (bolos_bool_t) SVC_Call(SYSCALL_os_aem_check_pin_ID, parameters); +bolos_bool_t os_aem_check_pin(unsigned char *aem_pin_buffer, unsigned char aem_pin_length) +{ + unsigned int parameters[2]; + parameters[0] = (unsigned int) aem_pin_buffer; + parameters[1] = (unsigned int) aem_pin_length; + return (bolos_bool_t) SVC_Call(SYSCALL_os_aem_check_pin_ID, parameters); } -void os_aem_invalidate_pin ( void ) { - unsigned int parameters[2]; - parameters[1] = 0; - SVC_Call(SYSCALL_os_aem_invalidate_pin_ID, parameters); - return; +void os_aem_invalidate_pin(void) +{ + unsigned int parameters[2]; + parameters[1] = 0; + SVC_Call(SYSCALL_os_aem_invalidate_pin_ID, parameters); + return; } -unsigned int os_aem_get_ptc ( void ) { - unsigned int parameters[2]; - parameters[1] = 0; - return (unsigned int) SVC_Call(SYSCALL_os_aem_get_ptc_ID, parameters); +unsigned int os_aem_get_ptc(void) +{ + unsigned int parameters[2]; + parameters[1] = 0; + return (unsigned int) SVC_Call(SYSCALL_os_aem_get_ptc_ID, parameters); } -bolos_bool_t os_aem_is_pin_validated ( void ) { - unsigned int parameters[2]; - parameters[1] = 0; - return (bolos_bool_t) SVC_Call(SYSCALL_os_aem_is_pin_validated_ID, parameters); +bolos_bool_t os_aem_is_pin_validated(void) +{ + unsigned int parameters[2]; + parameters[1] = 0; + return (bolos_bool_t) SVC_Call(SYSCALL_os_aem_is_pin_validated_ID, parameters); } -#endif // HAVE_AEM_PIN +#endif // HAVE_AEM_PIN -unsigned int os_endorsement_get_metadata ( unsigned char index, unsigned char * buffer ) { - unsigned int parameters[2]; - parameters[0] = (unsigned int)index; - parameters[1] = (unsigned int)buffer; - return (unsigned int) SVC_Call(SYSCALL_os_endorsement_get_metadata_ID, parameters); +unsigned int os_endorsement_get_metadata(unsigned char index, unsigned char *buffer) +{ + unsigned int parameters[2]; + parameters[0] = (unsigned int) index; + parameters[1] = (unsigned int) buffer; + return (unsigned int) SVC_Call(SYSCALL_os_endorsement_get_metadata_ID, parameters); } #if defined(HAVE_LANGUAGE_PACK) -void list_language_packs(UX_LOC_LANGUAGE_PACK_INFO *packs) { - unsigned int parameters [1]; - parameters[0] = (unsigned int)packs; - SVC_Call(SYSCALL_list_language_packs_ID, parameters); +void list_language_packs(UX_LOC_LANGUAGE_PACK_INFO *packs) +{ + unsigned int parameters[1]; + parameters[0] = (unsigned int) packs; + SVC_Call(SYSCALL_list_language_packs_ID, parameters); } -const LANGUAGE_PACK *get_language_pack(unsigned int language) { - unsigned int parameters [1]; - parameters[0] = language; - return (LANGUAGE_PACK *)SVC_Call(SYSCALL_get_language_pack_ID, parameters); +const LANGUAGE_PACK *get_language_pack(unsigned int language) +{ + unsigned int parameters[1]; + parameters[0] = language; + return (LANGUAGE_PACK *) SVC_Call(SYSCALL_get_language_pack_ID, parameters); } -#endif //defined(HAVE_LANGUAGE_PACK) +#endif // defined(HAVE_LANGUAGE_PACK) #if defined(HAVE_BACKGROUND_IMG) -uint8_t *fetch_background_img(bool allow_candidate) { - uint8_t parameters[1] = {(uint8_t) allow_candidate}; - return (uint8_t *) SVC_Call(SYSCALL_fetch_background_img, parameters); +uint8_t *fetch_background_img(bool allow_candidate) +{ + uint8_t parameters[1] = {(uint8_t) allow_candidate}; + return (uint8_t *) SVC_Call(SYSCALL_fetch_background_img, parameters); } -bolos_err_t delete_background_img(void) { - unsigned int parameters[1] = {0}; - return SVC_Call(SYSCALL_delete_background_img, parameters); +bolos_err_t delete_background_img(void) +{ + unsigned int parameters[1] = {0}; + return SVC_Call(SYSCALL_delete_background_img, parameters); } #endif #ifdef HAVE_SE_TOUCH -void touch_get_last_info( io_touch_info_t *info ) { - unsigned int parameters[1] = {(unsigned int) info}; - SVC_Call(SYSCALL_touch_get_last_info_ID, parameters); +void touch_get_last_info(io_touch_info_t *info) +{ + unsigned int parameters[1] = {(unsigned int) info}; + SVC_Call(SYSCALL_touch_get_last_info_ID, parameters); } -void touch_set_state(bool enable) { - unsigned int parameters[1] = {(unsigned int) enable}; - SVC_Call(SYSCALL_touch_set_state_ID, parameters); +void touch_set_state(bool enable) +{ + unsigned int parameters[1] = {(unsigned int) enable}; + SVC_Call(SYSCALL_touch_set_state_ID, parameters); } -uint8_t touch_exclude_borders(uint8_t excluded_borders) { - unsigned int parameters[1] = {(unsigned int) excluded_borders}; - return (uint8_t)SVC_Call(SYSCALL_touch_exclude_borders_ID, parameters); +uint8_t touch_exclude_borders(uint8_t excluded_borders) +{ + unsigned int parameters[1] = {(unsigned int) excluded_borders}; + return (uint8_t) SVC_Call(SYSCALL_touch_exclude_borders_ID, parameters); } #ifdef HAVE_TOUCH_READ_DEBUG_DATA_SYSCALL -uint8_t touch_switch_debug_mode_and_read(io_touch_debug_mode_t mode, uint8_t *read_buffer) { +uint8_t touch_switch_debug_mode_and_read(io_touch_debug_mode_t mode, uint8_t *read_buffer) +{ unsigned int parameters[2]; parameters[0] = (unsigned int) mode; parameters[1] = (unsigned int) read_buffer; - return (uint8_t)SVC_Call(SYSCALL_touch_debug_ID, parameters); + return (uint8_t) SVC_Call(SYSCALL_touch_debug_ID, parameters); } #endif -#endif // HAVE_SE_TOUCH +#endif // HAVE_SE_TOUCH #ifdef HAVE_IO_I2C -void io_i2c_setmode ( unsigned int speed_and_master, unsigned int address ) { - unsigned int parameters[2]; - parameters[0] = (unsigned int)speed_and_master; - parameters[1] = (unsigned int)address; - SVC_Call(SYSCALL_io_i2c_setmode_ID, parameters); - return; +void io_i2c_setmode(unsigned int speed_and_master, unsigned int address) +{ + unsigned int parameters[2]; + parameters[0] = (unsigned int) speed_and_master; + parameters[1] = (unsigned int) address; + SVC_Call(SYSCALL_io_i2c_setmode_ID, parameters); + return; } -void io_i2c_prepare ( unsigned int maxlength ) { - unsigned int parameters[2]; - parameters[0] = (unsigned int)maxlength; - parameters[1] = 0; - SVC_Call(SYSCALL_io_i2c_prepare_ID, parameters); - return; +void io_i2c_prepare(unsigned int maxlength) +{ + unsigned int parameters[2]; + parameters[0] = (unsigned int) maxlength; + parameters[1] = 0; + SVC_Call(SYSCALL_io_i2c_prepare_ID, parameters); + return; } -void io_i2c_xfer ( void * buffer, unsigned int length, unsigned int flags ) { - unsigned int parameters[3]; - parameters[0] = (unsigned int)buffer; - parameters[1] = (unsigned int)length; - parameters[2] = (unsigned int)flags; - SVC_Call(SYSCALL_io_i2c_xfer_ID, parameters); - return; +void io_i2c_xfer(void *buffer, unsigned int length, unsigned int flags) +{ + unsigned int parameters[3]; + parameters[0] = (unsigned int) buffer; + parameters[1] = (unsigned int) length; + parameters[2] = (unsigned int) flags; + SVC_Call(SYSCALL_io_i2c_xfer_ID, parameters); + return; } #ifndef BOLOS_RELEASE #ifdef BOLOS_DEBUG -void io_i2c_dumpstate ( void ) { - unsigned int parameters[2]; - parameters[1] = 0; - SVC_Call(SYSCALL_io_i2c_dumpstate_ID, parameters); - return; +void io_i2c_dumpstate(void) +{ + unsigned int parameters[2]; + parameters[1] = 0; + SVC_Call(SYSCALL_io_i2c_dumpstate_ID, parameters); + return; } -void io_debug ( char * chars, unsigned int len ) { - unsigned int parameters[2]; - parameters[0] = (unsigned int)chars; - parameters[1] = (unsigned int)len; - SVC_Call(SYSCALL_io_debug_ID, parameters); - return; +void io_debug(char *chars, unsigned int len) +{ + unsigned int parameters[2]; + parameters[0] = (unsigned int) chars; + parameters[1] = (unsigned int) len; + SVC_Call(SYSCALL_io_debug_ID, parameters); + return; } -#endif // BOLOS_DEBUG -#endif // BOLOS_RELEASE -#endif // HAVE_IO_I2C +#endif // BOLOS_DEBUG +#endif // BOLOS_RELEASE +#endif // HAVE_IO_I2C #ifdef DEBUG_OS_STACK_CONSUMPTION -int os_stack_operations(unsigned char mode) { - unsigned int parameters[2]; - parameters[0] = (unsigned int)mode; - return (unsigned int) SVC_Call(SYSCALL_os_stack_operations_ID, parameters); +int os_stack_operations(unsigned char mode) +{ + unsigned int parameters[2]; + parameters[0] = (unsigned int) mode; + return (unsigned int) SVC_Call(SYSCALL_os_stack_operations_ID, parameters); } -#endif // DEBUG_OS_STACK_CONSUMPTION +#endif // DEBUG_OS_STACK_CONSUMPTION #ifdef BOLOS_DEBUG -void log_debug ( const char * string ) { - unsigned int parameters[2]; - parameters[0] = (unsigned int)string; - parameters[1] = 0; - SVC_Call(SYSCALL_log_debug_ID, parameters); - return; -} - -void log_debug_nw ( const char * string ) { - unsigned int parameters[2]; - parameters[0] = (unsigned int)string; - parameters[1] = 0; - SVC_Call(SYSCALL_log_debug_nw_ID, parameters); - return; -} - -void log_debug_int ( char * fmt, unsigned int i ) { - unsigned int parameters[2]; - parameters[0] = (unsigned int)fmt; - parameters[1] = (unsigned int)i; - SVC_Call(SYSCALL_log_debug_int_ID, parameters); - return; -} - -void log_debug_int_nw ( char * fmt, unsigned int i ) { - unsigned int parameters[2]; - parameters[0] = (unsigned int)fmt; - parameters[1] = (unsigned int)i; - SVC_Call(SYSCALL_log_debug_int_nw_ID, parameters); - return; -} - -void log_mem ( unsigned int * adr, unsigned int len32 ) { - unsigned int parameters[2]; - parameters[0] = (unsigned int)adr; - parameters[1] = (unsigned int)len32; - SVC_Call(SYSCALL_log_mem_ID, parameters); - return; -} -#endif // BOLOS_DEBUG +void log_debug(const char *string) +{ + unsigned int parameters[2]; + parameters[0] = (unsigned int) string; + parameters[1] = 0; + SVC_Call(SYSCALL_log_debug_ID, parameters); + return; +} + +void log_debug_nw(const char *string) +{ + unsigned int parameters[2]; + parameters[0] = (unsigned int) string; + parameters[1] = 0; + SVC_Call(SYSCALL_log_debug_nw_ID, parameters); + return; +} + +void log_debug_int(char *fmt, unsigned int i) +{ + unsigned int parameters[2]; + parameters[0] = (unsigned int) fmt; + parameters[1] = (unsigned int) i; + SVC_Call(SYSCALL_log_debug_int_ID, parameters); + return; +} + +void log_debug_int_nw(char *fmt, unsigned int i) +{ + unsigned int parameters[2]; + parameters[0] = (unsigned int) fmt; + parameters[1] = (unsigned int) i; + SVC_Call(SYSCALL_log_debug_int_nw_ID, parameters); + return; +} + +void log_mem(unsigned int *adr, unsigned int len32) +{ + unsigned int parameters[2]; + parameters[0] = (unsigned int) adr; + parameters[1] = (unsigned int) len32; + SVC_Call(SYSCALL_log_mem_ID, parameters); + return; +} +#endif // BOLOS_DEBUG diff --git a/target/nanos/include/bolos_target.h b/target/nanos/include/bolos_target.h index 5d26862cf..fc8f089e8 100644 --- a/target/nanos/include/bolos_target.h +++ b/target/nanos/include/bolos_target.h @@ -1,5 +1,5 @@ #ifndef ST31 - #define ST31 -#endif // ST31 +#define ST31 +#endif // ST31 #define TARGET_ID 0x31100004 #define TARGET_NANOS diff --git a/target/nanos2/include/bolos_target.h b/target/nanos2/include/bolos_target.h index 60cadeeee..bc9b1e15d 100644 --- a/target/nanos2/include/bolos_target.h +++ b/target/nanos2/include/bolos_target.h @@ -1,5 +1,5 @@ #ifndef ST33K1M5 - #define ST33K1M5 -#endif // ST33K1M5 +#define ST33K1M5 +#endif // ST33K1M5 #define TARGET_ID 0x33100004 #define TARGET_NANOS2 diff --git a/target/nanox/include/bolos_target.h b/target/nanox/include/bolos_target.h index e237e1928..c051bcffc 100644 --- a/target/nanox/include/bolos_target.h +++ b/target/nanox/include/bolos_target.h @@ -1,5 +1,5 @@ #ifndef ST33 - #define ST33 -#endif // ST33 +#define ST33 +#endif // ST33 #define TARGET_ID 0x33000004 #define TARGET_NANOX diff --git a/target/stax/include/bolos_target.h b/target/stax/include/bolos_target.h index ffe4b7413..71277a37d 100644 --- a/target/stax/include/bolos_target.h +++ b/target/stax/include/bolos_target.h @@ -1,5 +1,5 @@ #ifndef ST33K1M5 - #define ST33K1M5 -#endif // ST33K1M5 +#define ST33K1M5 +#endif // ST33K1M5 #define TARGET_ID 0x33200004 #define TARGET_STAX diff --git a/unit-tests/lib_nbgl/test_nbgl_fonts.c b/unit-tests/lib_nbgl/test_nbgl_fonts.c index bc06091b0..59dffe2d7 100644 --- a/unit-tests/lib_nbgl/test_nbgl_fonts.c +++ b/unit-tests/lib_nbgl/test_nbgl_fonts.c @@ -12,34 +12,34 @@ const LANGUAGE_PACK *language_pack = NULL; -static void fetch_language_packs(void) { - // If we are looking for a language pack: - // - if the expected language is found then we'll use its begin/length range. - // - else we'll use the built-in package and need to reset allowed MMU range. +static void fetch_language_packs(void) +{ + // If we are looking for a language pack: + // - if the expected language is found then we'll use its begin/length range. + // - else we'll use the built-in package and need to reset allowed MMU range. - FILE *fptr = NULL; + FILE *fptr = NULL; - fptr = fopen("../bolos_pack_fr.bin","rb"); + fptr = fopen("../bolos_pack_fr.bin", "rb"); - assert_non_null(fptr); - if (fptr != NULL) { - fseek(fptr, 0, SEEK_END); + assert_non_null(fptr); + if (fptr != NULL) { + fseek(fptr, 0, SEEK_END); - uint32_t len = ftell(fptr); + uint32_t len = ftell(fptr); - fseek(fptr, 0, SEEK_SET); + fseek(fptr, 0, SEEK_SET); - uint8_t *source = (uint8_t*)malloc(len); + uint8_t *source = (uint8_t *) malloc(len); - assert_non_null(source); + assert_non_null(source); - assert_int_equal(fread((unsigned char*)source, 1, len, fptr),len); + assert_int_equal(fread((unsigned char *) source, 1, len, fptr), len); - fclose(fptr); + fclose(fptr); - language_pack = (LANGUAGE_PACK *)source; - - } + language_pack = (LANGUAGE_PACK *) source; + } } #include "nbgl_fonts.h" @@ -51,117 +51,133 @@ static void fetch_language_packs(void) { #include "nbgl_font_inter_semibold_24_1bpp.inc" #include "nbgl_font_inter_medium_32_1bpp.inc" -static const nbgl_font_t* const C_nbgl_fonts[] = { +static const nbgl_font_t *const C_nbgl_fonts[] = { #include "nbgl_font_rom_struct.inc" }; -static const unsigned int C_nbgl_fonts_count = sizeof(C_nbgl_fonts)/sizeof(C_nbgl_fonts[0]); - -const nbgl_font_t* nbgl_font_getFont(unsigned int fontId) { - unsigned int i = C_nbgl_fonts_count; - while(i--) { - // font id match this entry (non indexed array) - if (C_nbgl_fonts[i]->font_id == fontId) { - return C_nbgl_fonts[i]; +static const unsigned int C_nbgl_fonts_count = sizeof(C_nbgl_fonts) / sizeof(C_nbgl_fonts[0]); + +const nbgl_font_t *nbgl_font_getFont(unsigned int fontId) +{ + unsigned int i = C_nbgl_fonts_count; + while (i--) { + // font id match this entry (non indexed array) + if (C_nbgl_fonts[i]->font_id == fontId) { + return C_nbgl_fonts[i]; + } } - } - // id not found - return NULL; + // id not found + return NULL; } -void *pic(void *addr) { - return addr; +void *pic(void *addr) +{ + return addr; } -static void test_get_length(void **state __attribute__((unused))) { - char *str_with_unicode= "çoto"; - char *str_without_unicode= "toto"; - fetch_language_packs(); - - uint16_t width = nbgl_getTextWidth(BAGL_FONT_INTER_REGULAR_24px, str_without_unicode); - assert_int_equal(width,46); - uint16_t len = nbgl_getTextLength(str_without_unicode); - - assert_int_equal(len,4); - len = nbgl_getTextLength(str_with_unicode); - assert_int_equal(len,5); - assert_int_equal(strlen(str_with_unicode),5); - - width = nbgl_getTextWidth(BAGL_FONT_INTER_REGULAR_24px, str_with_unicode); - assert_int_equal(width,45); - - char myChar = 0x30; - width = nbgl_getCharWidth(BAGL_FONT_INTER_REGULAR_24px, &myChar); - assert_int_equal(width,15); - width = nbgl_getCharWidth(BAGL_FONT_INTER_REGULAR_24px, "ç"); - assert_int_equal(width,8); - - assert_int_equal(nbgl_getTextNbLines(str_without_unicode),1); - assert_int_equal(nbgl_getTextNbLines(str_with_unicode),1); - assert_int_equal(nbgl_getTextNbLines("bonjour\nau revoir"),2); - assert_int_equal(nbgl_getTextNbLines("bonjour\nau çevoir"),2); - - // '\n' is considered as end of string for nbgl_getTextLength - assert_int_equal(nbgl_getTextLength("bonjour\nau revoir"),7); - // 'ç' counts for 2 bytes - assert_int_equal(nbgl_getTextLength("bonçour\nau revoir"),8); - - nbgl_getTextMaxLenAndWidth(BAGL_FONT_INTER_REGULAR_24px,"totoour\nau revoir", 50, &len, &width, false); - assert_int_equal(len,4); - assert_int_equal(width,46); - - assert_int_equal(nbgl_getTextWidth(BAGL_FONT_INTER_REGULAR_24px,"au revoir"),100); - assert_int_equal(nbgl_getTextWidth(BAGL_FONT_INTER_REGULAR_24px,"totoour"),83); - assert_int_equal(strlen("totoour\nau revoir"),17); - nbgl_getTextMaxLenAndWidth(BAGL_FONT_INTER_REGULAR_24px,"totoour\nau revoir", 100, &len, &width, false); - assert_int_equal(len,7); - assert_int_equal(width,83); // width of latest line, doesn't mean anything - - uint8_t nbLines = nbgl_getTextNbLinesInWidth(BAGL_FONT_INTER_REGULAR_24px,"totoour\nau revoir", 100, false); - assert_int_equal(nbLines,2); - nbLines = nbgl_getTextNbLinesInWidth(BAGL_FONT_INTER_REGULAR_24px,"totoour\nau revoir", 60, false); - assert_int_equal(nbLines,4); - nbLines = nbgl_getTextNbLinesInWidth(BAGL_FONT_INTER_REGULAR_24px,"totoour\na", 50, false); - assert_int_equal(nbLines,3); - nbLines = nbgl_getTextNbLinesInWidth(BAGL_FONT_INTER_REGULAR_24px,"totoour\nau revoi", 50, false); - assert_int_equal(nbLines,4); - - nbLines = nbgl_getTextNbLinesInWidth(BAGL_FONT_INTER_REGULAR_24px,"totçour\nau revoir", 100, false); - assert_int_equal(nbLines,2); - nbLines = nbgl_getTextNbLinesInWidth(BAGL_FONT_INTER_REGULAR_24px,"totçour\nau revoir", 60, false); - assert_int_equal(nbLines,4); - nbLines = nbgl_getTextNbLinesInWidth(BAGL_FONT_INTER_REGULAR_24px,"totçour\na", 50, false); - assert_int_equal(nbLines,3); - nbLines = nbgl_getTextNbLinesInWidth(BAGL_FONT_INTER_REGULAR_24px,"totçour\nau revoi", 50, false); - assert_int_equal(nbLines,4); - - nbLines = nbgl_getTextNbLinesInWidth(BAGL_FONT_INTER_REGULAR_24px,"totçour au revoi", 100, true); - assert_int_equal(nbLines,2); - - nbgl_getTextMaxLenAndWidth(BAGL_FONT_INTER_REGULAR_24px,"totçour\nau revoir", 50, &len, &width, false); - assert_int_equal(len,5); - assert_int_equal(width,40); - - char textToWrap[32] = "toto"; - nbgl_textWrapOnNbLines(BAGL_FONT_INTER_SEMIBOLD_24px, textToWrap, 156, 2); - assert_string_equal(textToWrap,"toto"); - - strcpy(textToWrap,"bonjour tu aimes les mois"); - nbgl_textWrapOnNbLines(BAGL_FONT_INTER_SEMIBOLD_24px, textToWrap, 156, 2); - assert_string_equal(textToWrap,"bonjour tu\naimes les..."); - - strcpy(textToWrap,"bonjourtuaimestr les mois"); - nbgl_textWrapOnNbLines(BAGL_FONT_INTER_SEMIBOLD_24px, textToWrap, 156, 2); - assert_string_equal(textToWrap,"bonjourtuaimestr les..."); - - nbLines = nbgl_getTextNbLinesInWidth(BAGL_FONT_INTER_MEDIUM_32px, "AB WWWWWWWW WWW W", 200, true); - assert_int_equal(nbLines,4); - - int height = nbgl_getTextHeightInWidth(BAGL_FONT_INTER_MEDIUM_32px, "AB WWWWWWWW WWW W", 200, true); - assert_int_equal(height,160); +static void test_get_length(void **state __attribute__((unused))) +{ + char *str_with_unicode = "çoto"; + char *str_without_unicode = "toto"; + fetch_language_packs(); + + uint16_t width = nbgl_getTextWidth(BAGL_FONT_INTER_REGULAR_24px, str_without_unicode); + assert_int_equal(width, 46); + uint16_t len = nbgl_getTextLength(str_without_unicode); + + assert_int_equal(len, 4); + len = nbgl_getTextLength(str_with_unicode); + assert_int_equal(len, 5); + assert_int_equal(strlen(str_with_unicode), 5); + + width = nbgl_getTextWidth(BAGL_FONT_INTER_REGULAR_24px, str_with_unicode); + assert_int_equal(width, 45); + + char myChar = 0x30; + width = nbgl_getCharWidth(BAGL_FONT_INTER_REGULAR_24px, &myChar); + assert_int_equal(width, 15); + width = nbgl_getCharWidth(BAGL_FONT_INTER_REGULAR_24px, "ç"); + assert_int_equal(width, 8); + + assert_int_equal(nbgl_getTextNbLines(str_without_unicode), 1); + assert_int_equal(nbgl_getTextNbLines(str_with_unicode), 1); + assert_int_equal(nbgl_getTextNbLines("bonjour\nau revoir"), 2); + assert_int_equal(nbgl_getTextNbLines("bonjour\nau çevoir"), 2); + + // '\n' is considered as end of string for nbgl_getTextLength + assert_int_equal(nbgl_getTextLength("bonjour\nau revoir"), 7); + // 'ç' counts for 2 bytes + assert_int_equal(nbgl_getTextLength("bonçour\nau revoir"), 8); + + nbgl_getTextMaxLenAndWidth( + BAGL_FONT_INTER_REGULAR_24px, "totoour\nau revoir", 50, &len, &width, false); + assert_int_equal(len, 4); + assert_int_equal(width, 46); + + assert_int_equal(nbgl_getTextWidth(BAGL_FONT_INTER_REGULAR_24px, "au revoir"), 100); + assert_int_equal(nbgl_getTextWidth(BAGL_FONT_INTER_REGULAR_24px, "totoour"), 83); + assert_int_equal(strlen("totoour\nau revoir"), 17); + nbgl_getTextMaxLenAndWidth( + BAGL_FONT_INTER_REGULAR_24px, "totoour\nau revoir", 100, &len, &width, false); + assert_int_equal(len, 7); + assert_int_equal(width, 83); // width of latest line, doesn't mean anything + + uint8_t nbLines = nbgl_getTextNbLinesInWidth( + BAGL_FONT_INTER_REGULAR_24px, "totoour\nau revoir", 100, false); + assert_int_equal(nbLines, 2); + nbLines + = nbgl_getTextNbLinesInWidth(BAGL_FONT_INTER_REGULAR_24px, "totoour\nau revoir", 60, false); + assert_int_equal(nbLines, 4); + nbLines = nbgl_getTextNbLinesInWidth(BAGL_FONT_INTER_REGULAR_24px, "totoour\na", 50, false); + assert_int_equal(nbLines, 3); + nbLines + = nbgl_getTextNbLinesInWidth(BAGL_FONT_INTER_REGULAR_24px, "totoour\nau revoi", 50, false); + assert_int_equal(nbLines, 4); + + nbLines = nbgl_getTextNbLinesInWidth( + BAGL_FONT_INTER_REGULAR_24px, "totçour\nau revoir", 100, false); + assert_int_equal(nbLines, 2); + nbLines + = nbgl_getTextNbLinesInWidth(BAGL_FONT_INTER_REGULAR_24px, "totçour\nau revoir", 60, false); + assert_int_equal(nbLines, 4); + nbLines = nbgl_getTextNbLinesInWidth(BAGL_FONT_INTER_REGULAR_24px, "totçour\na", 50, false); + assert_int_equal(nbLines, 3); + nbLines + = nbgl_getTextNbLinesInWidth(BAGL_FONT_INTER_REGULAR_24px, "totçour\nau revoi", 50, false); + assert_int_equal(nbLines, 4); + + nbLines + = nbgl_getTextNbLinesInWidth(BAGL_FONT_INTER_REGULAR_24px, "totçour au revoi", 100, true); + assert_int_equal(nbLines, 2); + + nbgl_getTextMaxLenAndWidth( + BAGL_FONT_INTER_REGULAR_24px, "totçour\nau revoir", 50, &len, &width, false); + assert_int_equal(len, 5); + assert_int_equal(width, 40); + + char textToWrap[32] = "toto"; + nbgl_textWrapOnNbLines(BAGL_FONT_INTER_SEMIBOLD_24px, textToWrap, 156, 2); + assert_string_equal(textToWrap, "toto"); + + strcpy(textToWrap, "bonjour tu aimes les mois"); + nbgl_textWrapOnNbLines(BAGL_FONT_INTER_SEMIBOLD_24px, textToWrap, 156, 2); + assert_string_equal(textToWrap, "bonjour tu\naimes les..."); + + strcpy(textToWrap, "bonjourtuaimestr les mois"); + nbgl_textWrapOnNbLines(BAGL_FONT_INTER_SEMIBOLD_24px, textToWrap, 156, 2); + assert_string_equal(textToWrap, "bonjourtuaimestr les..."); + + nbLines + = nbgl_getTextNbLinesInWidth(BAGL_FONT_INTER_MEDIUM_32px, "AB WWWWWWWW WWW W", 200, true); + assert_int_equal(nbLines, 4); + + int height + = nbgl_getTextHeightInWidth(BAGL_FONT_INTER_MEDIUM_32px, "AB WWWWWWWW WWW W", 200, true); + assert_int_equal(height, 160); } -int main(int argc, char **argv) { - const struct CMUnitTest tests[] = {cmocka_unit_test(test_get_length)}; - return cmocka_run_group_tests(tests, NULL, NULL); +int main(int argc, char **argv) +{ + const struct CMUnitTest tests[] = {cmocka_unit_test(test_get_length)}; + return cmocka_run_group_tests(tests, NULL, NULL); } diff --git a/unit-tests/lib_nbgl/test_nbgl_screen.c b/unit-tests/lib_nbgl/test_nbgl_screen.c index 5d72e81e3..4ddce49cc 100644 --- a/unit-tests/lib_nbgl/test_nbgl_screen.c +++ b/unit-tests/lib_nbgl/test_nbgl_screen.c @@ -11,87 +11,94 @@ #include "nbgl_debug.h" #include "ux_loc.h" -#define UNUSED(x) (void)x +#define UNUSED(x) (void) x unsigned long gLogger = 0 -// | (1<container.nbChildren, 1); - assert_ptr_equal(screen->container.children, nbgl_screenGetElements(screen1)); - - // push a third screen and assert its index is 2, and that it is on top of stack - screen2 = nbgl_screenPush(&elements2, 2, NULL, NULL); - assert_int_equal(screen2, 2); - screen = (nbgl_screen_t *)nbgl_screenGetTop(); - assert_int_equal(screen->container.nbChildren, 2); - assert_ptr_equal(screen->container.children, nbgl_screenGetElements(screen2)); - - // push a fourth screen and assert its index is 3, and that it is on top of stack - screen3 = nbgl_screenPush(&elements3, 3, NULL, NULL); - assert_int_equal(screen3, 3); - screen = (nbgl_screen_t *)nbgl_screenGetTop(); - assert_int_equal(screen->container.nbChildren, 3); - assert_ptr_equal(screen->container.children, nbgl_screenGetElements(screen3)); - - // pop the fourth screen and assert the third one is on top of stack - nbgl_screenPop(screen3); - screen = (nbgl_screen_t *)nbgl_screenGetTop(); - assert_int_equal(screen->container.nbChildren, 2); - assert_ptr_equal(screen->container.children, nbgl_screenGetElements(screen2)); - - // pop the second screen and assert the third one is on top of stack - nbgl_screenPop(screen1); - screen = (nbgl_screen_t *)nbgl_screenGetTop(); - assert_int_equal(screen->container.nbChildren, 2); - assert_ptr_equal(screen->container.children, nbgl_screenGetElements(screen2)); - - // push a screen and assert its index is 1 (first unused index) - screen3 = nbgl_screenPush(&elements3, 3, NULL, NULL); - assert_int_equal(screen3, 1); +static void test_push_pop(void **state __attribute__((unused))) +{ + nbgl_obj_t **elements0, **elements1, **elements2, **elements3; + nbgl_screen_t *screen; + uint8_t screen1, screen2, screen3; + + // assert no screen at start-up + assert_null(nbgl_screenGetTop()); + + // add a first screen and assert the top is not null anymore + nbgl_screenSet(&elements0, 4, NULL, NULL); + assert_non_null(nbgl_screenGetTop()); + + // push a second screen and assert its index is 1, and that it is on top of stack + screen1 = nbgl_screenPush(&elements1, 1, NULL, NULL); + assert_int_equal(screen1, 1); + screen = (nbgl_screen_t *) nbgl_screenGetTop(); + assert_int_equal(screen->container.nbChildren, 1); + assert_ptr_equal(screen->container.children, nbgl_screenGetElements(screen1)); + + // push a third screen and assert its index is 2, and that it is on top of stack + screen2 = nbgl_screenPush(&elements2, 2, NULL, NULL); + assert_int_equal(screen2, 2); + screen = (nbgl_screen_t *) nbgl_screenGetTop(); + assert_int_equal(screen->container.nbChildren, 2); + assert_ptr_equal(screen->container.children, nbgl_screenGetElements(screen2)); + + // push a fourth screen and assert its index is 3, and that it is on top of stack + screen3 = nbgl_screenPush(&elements3, 3, NULL, NULL); + assert_int_equal(screen3, 3); + screen = (nbgl_screen_t *) nbgl_screenGetTop(); + assert_int_equal(screen->container.nbChildren, 3); + assert_ptr_equal(screen->container.children, nbgl_screenGetElements(screen3)); + + // pop the fourth screen and assert the third one is on top of stack + nbgl_screenPop(screen3); + screen = (nbgl_screen_t *) nbgl_screenGetTop(); + assert_int_equal(screen->container.nbChildren, 2); + assert_ptr_equal(screen->container.children, nbgl_screenGetElements(screen2)); + + // pop the second screen and assert the third one is on top of stack + nbgl_screenPop(screen1); + screen = (nbgl_screen_t *) nbgl_screenGetTop(); + assert_int_equal(screen->container.nbChildren, 2); + assert_ptr_equal(screen->container.children, nbgl_screenGetElements(screen2)); + + // push a screen and assert its index is 1 (first unused index) + screen3 = nbgl_screenPush(&elements3, 3, NULL, NULL); + assert_int_equal(screen3, 1); } -int main(int argc, char **argv) { - const struct CMUnitTest tests[] = {cmocka_unit_test(test_push_pop)}; - return cmocka_run_group_tests(tests, NULL, NULL); +int main(int argc, char **argv) +{ + const struct CMUnitTest tests[] = {cmocka_unit_test(test_push_pop)}; + return cmocka_run_group_tests(tests, NULL, NULL); } diff --git a/unit-tests/lib_standard_app/test_apdu_parser.c b/unit-tests/lib_standard_app/test_apdu_parser.c index 4c3399a9f..9189ce43e 100644 --- a/unit-tests/lib_standard_app/test_apdu_parser.c +++ b/unit-tests/lib_standard_app/test_apdu_parser.c @@ -9,13 +9,14 @@ #include "parser.h" -static void test_apdu_parser(void **state) { +static void test_apdu_parser(void **state) +{ (void) state; - uint8_t apdu_bad_min_len[] = {0xE0, 0x03, 0x00}; // less than 4 bytes - uint8_t apdu_bad_lc[] = {0xE0, 0x03, 0x00, 0x00, 0x01}; // Lc = 1 but no data - uint8_t apdu_no_lc[] = {0xE0, 0x03, 0x01, 0x02}; - uint8_t apdu_no_data[] = {0xE0, 0x03, 0x01, 0x02, 0x00}; - uint8_t apdu[] = {0xE0, 0x03, 0x01, 0x02, 0x05, 0x00, 0x01, 0x02, 0x03, 0x04}; + uint8_t apdu_bad_min_len[] = {0xE0, 0x03, 0x00}; // less than 4 bytes + uint8_t apdu_bad_lc[] = {0xE0, 0x03, 0x00, 0x00, 0x01}; // Lc = 1 but no data + uint8_t apdu_no_lc[] = {0xE0, 0x03, 0x01, 0x02}; + uint8_t apdu_no_data[] = {0xE0, 0x03, 0x01, 0x02, 0x00}; + uint8_t apdu[] = {0xE0, 0x03, 0x01, 0x02, 0x05, 0x00, 0x01, 0x02, 0x03, 0x04}; command_t cmd; @@ -54,7 +55,8 @@ static void test_apdu_parser(void **state) { assert_memory_equal(cmd.data, ((uint8_t[]){0x00, 0x01, 0x02, 0x03, 0x04}), cmd.lc); } -int main() { +int main() +{ const struct CMUnitTest tests[] = {cmocka_unit_test(test_apdu_parser)}; return cmocka_run_group_tests(tests, NULL, NULL); diff --git a/unit-tests/lib_standard_app/test_base58.c b/unit-tests/lib_standard_app/test_base58.c index f461c0011..07a06f24c 100644 --- a/unit-tests/lib_standard_app/test_base58.c +++ b/unit-tests/lib_standard_app/test_base58.c @@ -9,25 +9,27 @@ #include "base58.h" -static void test_base58(void **state) { +static void test_base58(void **state) +{ (void) state; - const char in[] = "USm3fpXnKG5EUBx2ndxBDMPVciP5hGey2Jh4NDv6gmeo1LkMeiKrLJUUBk6Z"; + const char in[] = "USm3fpXnKG5EUBx2ndxBDMPVciP5hGey2Jh4NDv6gmeo1LkMeiKrLJUUBk6Z"; const char expected_out[] = "The quick brown fox jumps over the lazy dog."; - uint8_t out[100] = {0}; - int out_len = base58_decode(in, sizeof(in) - 1, out, sizeof(out)); + uint8_t out[100] = {0}; + int out_len = base58_decode(in, sizeof(in) - 1, out, sizeof(out)); assert_int_equal(out_len, strlen(expected_out)); assert_string_equal((char *) out, expected_out); - const char in2[] = "The quick brown fox jumps over the lazy dog."; + const char in2[] = "The quick brown fox jumps over the lazy dog."; const char expected_out2[] = "USm3fpXnKG5EUBx2ndxBDMPVciP5hGey2Jh4NDv6gmeo1LkMeiKrLJUUBk6Z"; - char out2[100] = {0}; - int out_len2 = base58_encode((uint8_t *) in2, sizeof(in2) - 1, out2, sizeof(out2)); + char out2[100] = {0}; + int out_len2 = base58_encode((uint8_t *) in2, sizeof(in2) - 1, out2, sizeof(out2)); assert_int_equal(out_len2, strlen(expected_out2)); assert_string_equal((char *) out2, expected_out2); } -int main() { +int main() +{ const struct CMUnitTest tests[] = {cmocka_unit_test(test_base58)}; return cmocka_run_group_tests(tests, NULL, NULL); diff --git a/unit-tests/lib_standard_app/test_bip32.c b/unit-tests/lib_standard_app/test_bip32.c index b4895053f..75abd6c88 100644 --- a/unit-tests/lib_standard_app/test_bip32.c +++ b/unit-tests/lib_standard_app/test_bip32.c @@ -8,28 +8,26 @@ #include "bip32.h" -static void test_bip32_format(void **state) { +static void test_bip32_format(void **state) +{ (void) state; char output[30]; bool b = false; - b = bip32_path_format((const uint32_t[5]){0x8000002C, 0x80000000, 0x80000000, 0, 0}, - 5, - output, - sizeof(output)); + b = bip32_path_format( + (const uint32_t[5]){0x8000002C, 0x80000000, 0x80000000, 0, 0}, 5, output, sizeof(output)); assert_true(b); assert_string_equal(output, "44'/0'/0'/0/0"); - b = bip32_path_format((const uint32_t[5]){0x8000002C, 0x80000001, 0x80000000, 0, 0}, - 5, - output, - sizeof(output)); + b = bip32_path_format( + (const uint32_t[5]){0x8000002C, 0x80000001, 0x80000000, 0, 0}, 5, output, sizeof(output)); assert_true(b); assert_string_equal(output, "44'/1'/0'/0/0"); } -static void test_bad_bip32_format(void **state) { +static void test_bad_bip32_format(void **state) +{ (void) state; char output[30]; @@ -48,7 +46,8 @@ static void test_bad_bip32_format(void **state) { assert_false(b); } -static void test_bip32_read(void **state) { +static void test_bip32_read(void **state) +{ (void) state; // clang-format off diff --git a/unit-tests/lib_standard_app/test_buffer.c b/unit-tests/lib_standard_app/test_buffer.c index 2ded333bd..cdc5f17b4 100644 --- a/unit-tests/lib_standard_app/test_buffer.c +++ b/unit-tests/lib_standard_app/test_buffer.c @@ -8,11 +8,12 @@ #include "buffer.h" -static void test_buffer_can_read(void **state) { +static void test_buffer_can_read(void **state) +{ (void) state; - uint8_t temp[20] = {0}; - buffer_t buf = {.ptr = temp, .size = sizeof(temp), .offset = 0}; + uint8_t temp[20] = {0}; + buffer_t buf = {.ptr = temp, .size = sizeof(temp), .offset = 0}; assert_true(buffer_can_read(&buf, 20)); @@ -20,11 +21,12 @@ static void test_buffer_can_read(void **state) { assert_false(buffer_can_read(&buf, 1)); } -static void test_buffer_seek(void **state) { +static void test_buffer_seek(void **state) +{ (void) state; - uint8_t temp[20] = {0}; - buffer_t buf = {.ptr = temp, .size = sizeof(temp), .offset = 0}; + uint8_t temp[20] = {0}; + buffer_t buf = {.ptr = temp, .size = sizeof(temp), .offset = 0}; assert_true(buffer_can_read(&buf, 20)); @@ -41,7 +43,8 @@ static void test_buffer_seek(void **state) { assert_false(buffer_seek_set(&buf, 21)); // can't seek at offset 21 } -static void test_buffer_read(void **state) { +static void test_buffer_read(void **state) +{ (void) state; // clang-format off diff --git a/unit-tests/lib_standard_app/test_format.c b/unit-tests/lib_standard_app/test_format.c index d1092dde0..eae34f70d 100644 --- a/unit-tests/lib_standard_app/test_format.c +++ b/unit-tests/lib_standard_app/test_format.c @@ -9,7 +9,8 @@ #include "format.h" -static void test_format_i64(void **state) { +static void test_format_i64(void **state) +{ (void) state; char temp[22] = {0}; @@ -32,7 +33,8 @@ static void test_format_i64(void **state) { assert_string_equal(temp, "-9223372036854775808"); } -static void test_format_u64(void **state) { +static void test_format_u64(void **state) +{ (void) state; char temp[21] = {0}; @@ -50,7 +52,8 @@ static void test_format_u64(void **state) { assert_false(format_u64(temp, sizeof(temp) - 5, value)); } -static void test_format_fpu64(void **state) { +static void test_format_fpu64(void **state) +{ (void) state; char temp[22] = {0}; @@ -82,7 +85,8 @@ static void test_format_fpu64(void **state) { assert_false(format_fpu64(temp2, sizeof(temp2) - 20, amount, 18)); } -static void test_format_fpu64_trimmed(void **state) { +static void test_format_fpu64_trimmed(void **state) +{ (void) state; char temp[22] = {0}; @@ -108,12 +112,13 @@ static void test_format_fpu64_trimmed(void **state) { assert_string_equal(temp, "10"); // BTC } -static void test_format_hex(void **state) { +static void test_format_hex(void **state) +{ (void) state; uint8_t address[] = {0xde, 0xb, 0x29, 0x56, 0x69, 0xa9, 0xfd, 0x93, 0xd5, 0xf2, 0x8d, 0x9e, 0xc8, 0x5e, 0x40, 0xf4, 0xcb, 0x69, 0x7b, 0xae}; - char output[2 * sizeof(address) + 1] = {0}; + char output[2 * sizeof(address) + 1] = {0}; assert_int_equal(2 * sizeof(address) + 1, format_hex(address, sizeof(address), output, sizeof(output))); @@ -121,7 +126,8 @@ static void test_format_hex(void **state) { assert_int_equal(-1, format_hex(address, sizeof(address), output, sizeof(address))); } -int main() { +int main() +{ const struct CMUnitTest tests[] = {cmocka_unit_test(test_format_i64), cmocka_unit_test(test_format_u64), cmocka_unit_test(test_format_fpu64), diff --git a/unit-tests/lib_standard_app/test_write.c b/unit-tests/lib_standard_app/test_write.c index 7cb89fc54..3cb8f3f0a 100644 --- a/unit-tests/lib_standard_app/test_write.c +++ b/unit-tests/lib_standard_app/test_write.c @@ -9,7 +9,8 @@ #include "write.h" -static void test_write(void **state) { +static void test_write(void **state) +{ (void) state; uint8_t tmp2[2] = {0}; @@ -57,7 +58,8 @@ static void test_write(void **state) { assert_memory_equal(tmp8, expected8, sizeof(expected8)); } -int main() { +int main() +{ const struct CMUnitTest tests[] = {cmocka_unit_test(test_write)}; return cmocka_run_group_tests(tests, NULL, NULL);